Merge inbound to mozilla-central. a=merge
authorshindli <shindli@mozilla.com>
Wed, 04 Jul 2018 00:56:24 +0300
changeset 424924 987ea0d6a000b95cf93928b25a74a7fb1dfe37b2
parent 424836 b636a45b545e8739212cce05b25db9f0f373cfe0 (current diff)
parent 424923 5d23b6e0b74d74eee52d7af5fa47573ef8afe979 (diff)
child 424925 56833e08843f5e7e7ef5f909be5a6ba28a51d294
child 424971 00de580e868fa783efe54354f426851c1eec7428
push id65892
push usershindli@mozilla.com
push dateTue, 03 Jul 2018 22:01:53 +0000
treeherderautoland@56833e08843f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone63.0a1
first release with
nightly linux32
987ea0d6a000 / 63.0a1 / 20180703220118 / files
nightly linux64
987ea0d6a000 / 63.0a1 / 20180703220118 / files
nightly mac
987ea0d6a000 / 63.0a1 / 20180703220118 / files
nightly win64
987ea0d6a000 / 63.0a1 / 20180703220118 / files
nightly win32
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win64
Merge inbound to mozilla-central. a=merge
devtools/server/actors/webconsole/screenshot.js
devtools/shared/webconsole/screenshot-helper.js
dom/media/mediasource/AutoTaskQueue.h
modules/libpref/init/all.js
--- a/accessible/ipc/win/HandlerProvider.cpp
+++ b/accessible/ipc/win/HandlerProvider.cpp
@@ -159,43 +159,16 @@ HandlerProvider::GetHandlerPayloadSize(N
     *aOutPayloadSize = mscom::StructToStream::GetEmptySize();
     return S_OK;
   }
 
   *aOutPayloadSize = mSerializer->GetSize();
   return S_OK;
 }
 
-template <typename CondFnT, typename ExeFnT>
-class MOZ_RAII ExecuteWhen final
-{
-public:
-  ExecuteWhen(CondFnT& aCondFn, ExeFnT& aExeFn)
-    : mCondFn(aCondFn)
-    , mExeFn(aExeFn)
-  {
-  }
-
-  ~ExecuteWhen()
-  {
-    if (mCondFn()) {
-      mExeFn();
-    }
-  }
-
-  ExecuteWhen(const ExecuteWhen&) = delete;
-  ExecuteWhen(ExecuteWhen&&) = delete;
-  ExecuteWhen& operator=(const ExecuteWhen&) = delete;
-  ExecuteWhen& operator=(ExecuteWhen&&) = delete;
-
-private:
-  CondFnT&  mCondFn;
-  ExeFnT&   mExeFn;
-};
-
 void
 HandlerProvider::BuildStaticIA2Data(
   NotNull<mscom::IInterceptor*> aInterceptor,
   StaticIA2Data* aOutData)
 {
   MOZ_ASSERT(aOutData);
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mTargetUnk);
@@ -273,17 +246,18 @@ HandlerProvider::BuildDynamicIA2Data(Dyn
   auto hasFailed = [&hr]() -> bool {
     return FAILED(hr);
   };
 
   auto cleanup = [this, aOutIA2Data]() -> void {
     CleanupDynamicIA2Data(*aOutIA2Data);
   };
 
-  ExecuteWhen<decltype(hasFailed), decltype(cleanup)> onFail(hasFailed, cleanup);
+  mscom::ExecuteWhen<decltype(hasFailed), decltype(cleanup)>
+    onFail(hasFailed, cleanup);
 
   const VARIANT kChildIdSelf = {VT_I4};
   VARIANT varVal;
 
   hr = target->accLocation(&aOutIA2Data->mLeft, &aOutIA2Data->mTop,
                            &aOutIA2Data->mWidth, &aOutIA2Data->mHeight,
                            kChildIdSelf);
   if (FAILED(hr)) {
--- a/browser/components/downloads/DownloadsCommon.jsm
+++ b/browser/components/downloads/DownloadsCommon.jsm
@@ -58,17 +58,16 @@ XPCOMUtils.defineLazyGetter(this, "Downl
 
 const kDownloadsStringBundleUrl =
   "chrome://browser/locale/downloads/downloads.properties";
 
 const kDownloadsStringsRequiringFormatting = {
   sizeWithUnits: true,
   statusSeparator: true,
   statusSeparatorBeforeNumber: true,
-  fileExecutableSecurityWarning: true
 };
 
 const kDownloadsStringsRequiringPluralForm = {
   otherDownloads3: true
 };
 
 const kMaxHistoryResultsForLimitedView = 42;
 
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,5 +1,5 @@
 This is the PDF.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 2.0.641
+Current extension version is: 2.0.661
 
-Taken from upstream commit: 6fa2c779
+Taken from upstream commit: 42922c9a
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '2.0.641';
-var pdfjsBuild = '6fa2c779';
+var pdfjsVersion = '2.0.661';
+var pdfjsBuild = '42922c9a';
 var pdfjsSharedUtil = __w_pdfjs_require__(1);
 var pdfjsDisplayAPI = __w_pdfjs_require__(6);
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(18);
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(19);
 var pdfjsDisplayDOMUtils = __w_pdfjs_require__(7);
 var pdfjsDisplaySVG = __w_pdfjs_require__(20);
 let pdfjsDisplayWorkerOptions = __w_pdfjs_require__(12);
 let pdfjsDisplayAPICompatibility = __w_pdfjs_require__(9);
@@ -4218,17 +4218,17 @@ function _fetchDocument(worker, source, 
     return Promise.reject(new Error('Worker was destroyed'));
   }
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
   }
   return worker.messageHandler.sendWithPromise('GetDocRequest', {
     docId,
-    apiVersion: '2.0.641',
+    apiVersion: '2.0.661',
     source: {
       data: source.data,
       url: source.url,
       password: source.password,
       disableAutoFetch: source.disableAutoFetch,
       rangeChunkSize: source.rangeChunkSize,
       length: source.length
     },
@@ -5463,26 +5463,26 @@ var InternalRenderTask = function Intern
     this.capability = (0, _util.createPromiseCapability)();
     this.task = new RenderTask(this);
     this._continueBound = this._continue.bind(this);
     this._scheduleNextBound = this._scheduleNext.bind(this);
     this._nextBound = this._next.bind(this);
     this._canvas = params.canvasContext.canvas;
   }
   InternalRenderTask.prototype = {
-    initializeGraphics: function InternalRenderTask_initializeGraphics(transparency) {
+    initializeGraphics(transparency) {
+      if (this.cancelled) {
+        return;
+      }
       if (this._canvas) {
         if (canvasInRendering.has(this._canvas)) {
           throw new Error('Cannot use the same canvas during multiple render() operations. ' + 'Use different canvas or ensure previous operations were ' + 'cancelled or completed.');
         }
         canvasInRendering.set(this._canvas, this);
       }
-      if (this.cancelled) {
-        return;
-      }
       if (this._pdfBug && _global_scope2.default.StepperManager && _global_scope2.default.StepperManager.enabled) {
         this.stepper = _global_scope2.default.StepperManager.create(this.pageNumber - 1);
         this.stepper.init(this.operatorList);
         this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
       }
       var params = this.params;
       this.gfx = new _canvas.CanvasGraphics(params.canvasContext, this.commonObjs, this.objs, this.canvasFactory, this.webGLContext, params.imageLayer);
       this.gfx.beginDrawing({
@@ -5558,18 +5558,18 @@ var InternalRenderTask = function Intern
         }
       });
     }
   };
   return InternalRenderTask;
 }();
 var version, build;
 {
-  exports.version = version = '2.0.641';
-  exports.build = build = '6fa2c779';
+  exports.version = version = '2.0.661';
+  exports.build = build = '42922c9a';
 }
 exports.getDocument = getDocument;
 exports.LoopbackPort = LoopbackPort;
 exports.PDFDataRangeTransport = PDFDataRangeTransport;
 exports.PDFWorker = PDFWorker;
 exports.PDFDocumentProxy = PDFDocumentProxy;
 exports.PDFPageProxy = PDFPageProxy;
 exports.setPDFNetworkStreamFactory = setPDFNetworkStreamFactory;
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '2.0.641';
-var pdfjsBuild = '6fa2c779';
+var pdfjsVersion = '2.0.661';
+var pdfjsBuild = '42922c9a';
 var pdfjsCoreWorker = __w_pdfjs_require__(1);
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
@@ -322,17 +322,17 @@ var WorkerMessageHandler = {
     });
   },
   createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     let apiVersion = docParams.apiVersion;
-    let workerVersion = '2.0.641';
+    let workerVersion = '2.0.661';
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
     var docId = docParams.docId;
     var docBaseUrl = docParams.docBaseUrl;
     var workerHandlerName = docParams.docId + '_worker';
     var handler = new _message_handler.MessageHandler(workerHandlerName, docId, port);
     handler.postMessageTransfers = docParams.postMessageTransfers;
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -565,17 +565,20 @@ let PDFViewerApplication = {
         l10n: this.l10n
       });
       pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
       this.pdfHistory = new _pdf_history.PDFHistory({
         linkService: pdfLinkService,
         eventBus
       });
       pdfLinkService.setHistory(this.pdfHistory);
-      this.findController = new _pdf_find_controller.PDFFindController({ pdfViewer: this.pdfViewer });
+      this.findController = new _pdf_find_controller.PDFFindController({
+        pdfViewer: this.pdfViewer,
+        eventBus
+      });
       this.findController.onUpdateResultsCount = matchCount => {
         if (this.supportsIntegratedFind) {
           return;
         }
         this.findBar.updateResultsCount(matchCount);
       };
       this.findController.onUpdateState = (state, previous, matchCount) => {
         if (this.supportsIntegratedFind) {
@@ -927,34 +930,33 @@ let PDFViewerApplication = {
       this.loadingBar.hide();
       firstPagePromise.then(() => {
         this.eventBus.dispatch('documentload', { source: this });
       });
     });
     let pageModePromise = pdfDocument.getPageMode().catch(function () {});
     this.toolbar.setPagesCount(pdfDocument.numPages, false);
     this.secondaryToolbar.setPagesCount(pdfDocument.numPages);
-    let id = this.documentFingerprint = pdfDocument.fingerprint;
-    let store = this.store = new _view_history.ViewHistory(id);
+    const store = this.store = new _view_history.ViewHistory(pdfDocument.fingerprint);
     let baseDocumentUrl;
     baseDocumentUrl = this.baseUrl;
     this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl);
     this.pdfDocumentProperties.setDocument(pdfDocument, this.url);
     let pdfViewer = this.pdfViewer;
     pdfViewer.setDocument(pdfDocument);
     let firstPagePromise = pdfViewer.firstPagePromise;
     let pagesPromise = pdfViewer.pagesPromise;
     let onePageRendered = pdfViewer.onePageRendered;
     let pdfThumbnailViewer = this.pdfThumbnailViewer;
     pdfThumbnailViewer.setDocument(pdfDocument);
     firstPagePromise.then(pdfPage => {
       this.loadingBar.setWidth(this.appConfig.viewerContainer);
       if (!_app_options.AppOptions.get('disableHistory') && !this.isViewerEmbedded) {
         let resetHistory = !_app_options.AppOptions.get('showPreviousViewOnLoad');
-        this.pdfHistory.initialize(id, resetHistory);
+        this.pdfHistory.initialize(pdfDocument.fingerprint, resetHistory);
         if (this.pdfHistory.initialBookmark) {
           this.initialBookmark = this.pdfHistory.initialBookmark;
           this.initialRotation = this.pdfHistory.initialRotation;
         }
       }
       let initialParams = {
         bookmark: null,
         hash: null
@@ -975,22 +977,18 @@ let PDFViewerApplication = {
         let rotation = null;
         let sidebarView = _app_options.AppOptions.get('sidebarViewOnLoad');
         let scrollMode = _app_options.AppOptions.get('scrollModeOnLoad');
         let spreadMode = _app_options.AppOptions.get('spreadModeOnLoad');
         if (values.page && _app_options.AppOptions.get('showPreviousViewOnLoad')) {
           hash = 'page=' + values.page + '&zoom=' + (zoom || values.zoom) + ',' + values.scrollLeft + ',' + values.scrollTop;
           rotation = parseInt(values.rotation, 10);
           sidebarView = sidebarView || values.sidebarView | 0;
-          if (values.scrollMode !== null) {
-            scrollMode = values.scrollMode;
-          }
-          if (values.spreadMode !== null) {
-            spreadMode = values.spreadMode;
-          }
+          scrollMode = scrollMode || values.scrollMode | 0;
+          spreadMode = spreadMode || values.spreadMode | 0;
         }
         if (pageMode && !_app_options.AppOptions.get('disablePageMode')) {
           sidebarView = sidebarView || apiPageModeToSidebarView(pageMode);
         }
         return {
           hash,
           rotation,
           sidebarView,
@@ -1123,29 +1121,31 @@ let PDFViewerApplication = {
       this.externalServices.reportTelemetry({
         type: 'documentInfo',
         version: versionId,
         generator: generatorId,
         formType
       });
     });
   },
-  setInitialView(storedHash, values = {}) {
-    let { rotation, sidebarView, scrollMode, spreadMode } = values;
+  setInitialView(storedHash, { rotation, sidebarView, scrollMode, spreadMode } = {}) {
     let setRotation = angle => {
       if ((0, _ui_utils.isValidRotation)(angle)) {
         this.pdfViewer.pagesRotation = angle;
       }
     };
-    if (Number.isInteger(scrollMode)) {
-      this.pdfViewer.setScrollMode(scrollMode);
-    }
-    if (Number.isInteger(spreadMode)) {
-      this.pdfViewer.setSpreadMode(spreadMode);
-    }
+    let setViewerModes = (scroll, spread) => {
+      if (Number.isInteger(scroll)) {
+        this.pdfViewer.scrollMode = scroll;
+      }
+      if (Number.isInteger(spread)) {
+        this.pdfViewer.spreadMode = spread;
+      }
+    };
+    setViewerModes(scrollMode, spreadMode);
     this.isInitialViewSet = true;
     this.pdfSidebar.setInitialView(sidebarView);
     if (this.initialBookmark) {
       setRotation(this.initialRotation);
       delete this.initialRotation;
       this.pdfLinkService.setHash(this.initialBookmark);
       this.initialBookmark = null;
     } else if (storedHash) {
@@ -1579,20 +1579,20 @@ function webViewerScaleChanged(evt) {
 }
 function webViewerRotateCw() {
   PDFViewerApplication.rotatePages(90);
 }
 function webViewerRotateCcw() {
   PDFViewerApplication.rotatePages(-90);
 }
 function webViewerSwitchScrollMode(evt) {
-  PDFViewerApplication.pdfViewer.setScrollMode(evt.mode);
+  PDFViewerApplication.pdfViewer.scrollMode = evt.mode;
 }
 function webViewerSwitchSpreadMode(evt) {
-  PDFViewerApplication.pdfViewer.setSpreadMode(evt.mode);
+  PDFViewerApplication.pdfViewer.spreadMode = evt.mode;
 }
 function webViewerDocumentProperties() {
   PDFViewerApplication.pdfDocumentProperties.open();
 }
 function webViewerFind(evt) {
   PDFViewerApplication.findController.executeCommand('find' + evt.type, {
     query: evt.query,
     phraseSearch: evt.phraseSearch,
@@ -3217,16 +3217,24 @@ const defaultOptions = {
   showPreviousViewOnLoad: {
     value: true,
     kind: OptionKind.VIEWER
   },
   sidebarViewOnLoad: {
     value: 0,
     kind: OptionKind.VIEWER
   },
+  scrollModeOnLoad: {
+    value: 0,
+    kind: OptionKind.VIEWER
+  },
+  spreadModeOnLoad: {
+    value: 0,
+    kind: OptionKind.VIEWER
+  },
   textLayerMode: {
     value: 1,
     kind: OptionKind.VIEWER
   },
   useOnlyCssZoom: {
     value: false,
     kind: OptionKind.VIEWER
   },
@@ -4174,16 +4182,18 @@ exports.PDFFindBar = PDFFindBar;
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFFindController = exports.FindState = undefined;
 
 var _pdfjsLib = __webpack_require__(3);
 
+var _dom_events = __webpack_require__(10);
+
 var _ui_utils = __webpack_require__(2);
 
 const FindState = {
   FOUND: 0,
   NOT_FOUND: 1,
   WRAPPED: 2,
   PENDING: 3
 };
@@ -4199,18 +4209,19 @@ const CHARACTERS_TO_NORMALIZE = {
   '\u201D': '"',
   '\u201E': '"',
   '\u201F': '"',
   '\u00BC': '1/4',
   '\u00BD': '1/2',
   '\u00BE': '3/4'
 };
 class PDFFindController {
-  constructor({ pdfViewer }) {
+  constructor({ pdfViewer, eventBus = (0, _dom_events.getGlobalEventBus)() }) {
     this.pdfViewer = pdfViewer;
+    this.eventBus = eventBus;
     this.onUpdateResultsCount = null;
     this.onUpdateState = null;
     this.reset();
     let replace = Object.keys(CHARACTERS_TO_NORMALIZE).join('');
     this.normalizationRegex = new RegExp('[' + replace + ']', 'g');
   }
   reset() {
     this.startedTextExtraction = false;
@@ -4230,17 +4241,21 @@ class PDFFindController {
       matchIdx: null
     };
     this.pagesToSearch = null;
     this.resumePageIdx = null;
     this.state = null;
     this.dirtyMatch = false;
     this.findTimeout = null;
     this._firstPagePromise = new Promise(resolve => {
-      this.resolveFirstPage = resolve;
+      const eventBus = this.eventBus;
+      eventBus.on('pagesinit', function onPagesInit() {
+        eventBus.off('pagesinit', onPagesInit);
+        resolve();
+      });
     });
   }
   executeCommand(cmd, state) {
     if (this.state === null || cmd !== 'findagain') {
       this.dirtyMatch = true;
     }
     this.state = state;
     this._updateUIState(FindState.PENDING);
@@ -6337,28 +6352,28 @@ class PDFViewer extends _base_viewer.Bas
   get _setDocumentViewerElement() {
     return (0, _pdfjsLib.shadow)(this, '_setDocumentViewerElement', this.viewer);
   }
   _scrollIntoView({ pageDiv, pageSpot = null }) {
     if (!pageSpot && !this.isInPresentationMode) {
       const left = pageDiv.offsetLeft + pageDiv.clientLeft;
       const right = left + pageDiv.clientWidth;
       const { scrollLeft, clientWidth } = this.container;
-      if (this.scrollMode === _base_viewer.ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) {
+      if (this._scrollMode === _base_viewer.ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) {
         pageSpot = {
           left: 0,
           top: 0
         };
       }
     }
     (0, _ui_utils.scrollIntoView)(pageDiv, pageSpot);
   }
   _getVisiblePages() {
     if (!this.isInPresentationMode) {
-      return (0, _ui_utils.getVisibleElements)(this.container, this._pages, true, this.scrollMode === _base_viewer.ScrollMode.HORIZONTAL);
+      return (0, _ui_utils.getVisibleElements)(this.container, this._pages, true, this._scrollMode === _base_viewer.ScrollMode.HORIZONTAL);
     }
     let currentPage = this._pages[this._currentPageNumber - 1];
     let visible = [{
       id: currentPage.id,
       view: currentPage
     }];
     return {
       first: currentPage,
@@ -6395,84 +6410,17 @@ class PDFViewer extends _base_viewer.Bas
     }
     this._updateLocation(visible.first);
     this.eventBus.dispatch('updateviewarea', {
       source: this,
       location: this._location
     });
   }
   get _isScrollModeHorizontal() {
-    return this.isInPresentationMode ? false : this.scrollMode === _base_viewer.ScrollMode.HORIZONTAL;
-  }
-  setScrollMode(mode) {
-    if (mode === this.scrollMode) {
-      return;
-    }
-    super.setScrollMode(mode);
-    this.eventBus.dispatch('scrollmodechanged', { mode });
-    this._updateScrollModeClasses();
-    if (!this.pdfDocument) {
-      return;
-    }
-    const pageNumber = this._currentPageNumber;
-    if (isNaN(this._currentScaleValue)) {
-      this._setScale(this._currentScaleValue, true);
-    }
-    this.scrollPageIntoView({ pageNumber });
-    this.update();
-  }
-  _updateScrollModeClasses() {
-    const { scrollMode, viewer } = this;
-    if (scrollMode === _base_viewer.ScrollMode.HORIZONTAL) {
-      viewer.classList.add('scrollHorizontal');
-    } else {
-      viewer.classList.remove('scrollHorizontal');
-    }
-    if (scrollMode === _base_viewer.ScrollMode.WRAPPED) {
-      viewer.classList.add('scrollWrapped');
-    } else {
-      viewer.classList.remove('scrollWrapped');
-    }
-  }
-  setSpreadMode(mode) {
-    if (mode === this.spreadMode) {
-      return;
-    }
-    super.setSpreadMode(mode);
-    this.eventBus.dispatch('spreadmodechanged', { mode });
-    this._regroupSpreads();
-  }
-  _regroupSpreads() {
-    if (!this.pdfDocument) {
-      return;
-    }
-    const viewer = this.viewer,
-          pages = this._pages;
-    viewer.textContent = '';
-    if (this.spreadMode === _base_viewer.SpreadMode.NONE) {
-      for (let i = 0, iMax = pages.length; i < iMax; ++i) {
-        viewer.appendChild(pages[i].div);
-      }
-    } else {
-      const parity = this.spreadMode - 1;
-      let spread = null;
-      for (let i = 0, iMax = pages.length; i < iMax; ++i) {
-        if (spread === null) {
-          spread = document.createElement('div');
-          spread.className = 'spread';
-          viewer.appendChild(spread);
-        } else if (i % 2 === parity) {
-          spread = spread.cloneNode(false);
-          viewer.appendChild(spread);
-        }
-        spread.appendChild(pages[i].div);
-      }
-    }
-    this.scrollPageIntoView({ pageNumber: this._currentPageNumber });
-    this.update();
+    return this.isInPresentationMode ? false : this._scrollMode === _base_viewer.ScrollMode.HORIZONTAL;
   }
 }
 exports.PDFViewer = PDFViewer;
 
 /***/ }),
 /* 25 */
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -6565,34 +6513,29 @@ class BaseViewer {
     this.imageResourcesPath = options.imageResourcesPath || '';
     this.renderInteractiveForms = options.renderInteractiveForms || false;
     this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
     this.renderer = options.renderer || _ui_utils.RendererType.CANVAS;
     this.enableWebGL = options.enableWebGL || false;
     this.useOnlyCssZoom = options.useOnlyCssZoom || false;
     this.maxCanvasPixels = options.maxCanvasPixels;
     this.l10n = options.l10n || _ui_utils.NullL10n;
-    this.scrollMode = options.scrollMode || ScrollMode.VERTICAL;
-    this.spreadMode = options.spreadMode || SpreadMode.NONE;
     this.defaultRenderingQueue = !options.renderingQueue;
     if (this.defaultRenderingQueue) {
       this.renderingQueue = new _pdf_rendering_queue.PDFRenderingQueue();
       this.renderingQueue.setViewer(this);
     } else {
       this.renderingQueue = options.renderingQueue;
     }
     this.scroll = (0, _ui_utils.watchScroll)(this.container, this._scrollUpdate.bind(this));
     this.presentationModeState = _ui_utils.PresentationModeState.UNKNOWN;
     this._resetView();
     if (this.removePageBorders) {
       this.viewer.classList.add('removePageBorders');
     }
-    if (this.scrollMode !== ScrollMode.VERTICAL) {
-      this._updateScrollModeClasses();
-    }
   }
   get pagesCount() {
     return this._pages.length;
   }
   getPageView(index) {
     return this._pages[index];
   }
   get pageViewsReady() {
@@ -6760,18 +6703,18 @@ class BaseViewer {
           enableWebGL: this.enableWebGL,
           useOnlyCssZoom: this.useOnlyCssZoom,
           maxCanvasPixels: this.maxCanvasPixels,
           l10n: this.l10n
         });
         bindOnAfterAndBeforeDraw(pageView);
         this._pages.push(pageView);
       }
-      if (this.spreadMode !== SpreadMode.NONE) {
-        this._regroupSpreads();
+      if (this._spreadMode !== SpreadMode.NONE) {
+        this._updateSpreadMode();
       }
       onePageRenderedCapability.promise.then(() => {
         if (pdfDocument.loadingParams['disableAutoFetch']) {
           pagesCapability.resolve();
           return;
         }
         let getPagesLeft = pagesCount;
         for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
@@ -6791,19 +6734,16 @@ class BaseViewer {
             }
           });
         }
       });
       this.eventBus.dispatch('pagesinit', { source: this });
       if (this.defaultRenderingQueue) {
         this.update();
       }
-      if (this.findController) {
-        this.findController.resolveFirstPage();
-      }
     }).catch(reason => {
       console.error('Unable to initialize viewer', reason);
     });
   }
   setPageLabels(labels) {
     if (!this.pdfDocument) {
       return;
     }
@@ -6827,17 +6767,20 @@ class BaseViewer {
     this._currentScale = _ui_utils.UNKNOWN_SCALE;
     this._currentScaleValue = null;
     this._pageLabels = null;
     this._buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE);
     this._location = null;
     this._pagesRotation = 0;
     this._pagesRequests = [];
     this._pageViewsReady = false;
+    this._scrollMode = ScrollMode.VERTICAL;
+    this._spreadMode = SpreadMode.NONE;
     this.viewer.textContent = '';
+    this._updateScrollMode();
   }
   _scrollUpdate() {
     if (this.pagesCount === 0) {
       return;
     }
     this.update();
   }
   _scrollIntoView({ pageDiv, pageSpot = null, pageNumber = null }) {
@@ -7187,30 +7130,106 @@ class BaseViewer {
       }
       return {
         width: size.height,
         height: size.width,
         rotation: (size.rotation + 90) % 360
       };
     });
   }
-  setScrollMode(mode) {
+  get scrollMode() {
+    return this._scrollMode;
+  }
+  set scrollMode(mode) {
+    if (this._scrollMode === mode) {
+      return;
+    }
     if (!Number.isInteger(mode) || !Object.values(ScrollMode).includes(mode)) {
       throw new Error(`Invalid scroll mode: ${mode}`);
     }
-    this.scrollMode = mode;
-  }
-  _updateScrollModeClasses() {}
-  setSpreadMode(mode) {
+    this._scrollMode = mode;
+    this.eventBus.dispatch('scrollmodechanged', {
+      source: this,
+      mode
+    });
+    this._updateScrollMode(this._currentPageNumber);
+  }
+  _updateScrollMode(pageNumber = null) {
+    const scrollMode = this._scrollMode,
+          viewer = this.viewer;
+    if (scrollMode === ScrollMode.HORIZONTAL) {
+      viewer.classList.add('scrollHorizontal');
+    } else {
+      viewer.classList.remove('scrollHorizontal');
+    }
+    if (scrollMode === ScrollMode.WRAPPED) {
+      viewer.classList.add('scrollWrapped');
+    } else {
+      viewer.classList.remove('scrollWrapped');
+    }
+    if (!this.pdfDocument || !pageNumber) {
+      return;
+    }
+    if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
+      this._setScale(this._currentScaleValue, true);
+    }
+    this.scrollPageIntoView({ pageNumber });
+    this.update();
+  }
+  setScrollMode(mode) {}
+  get spreadMode() {
+    return this._spreadMode;
+  }
+  set spreadMode(mode) {
+    if (this._spreadMode === mode) {
+      return;
+    }
     if (!Number.isInteger(mode) || !Object.values(SpreadMode).includes(mode)) {
       throw new Error(`Invalid spread mode: ${mode}`);
     }
-    this.spreadMode = mode;
-  }
-  _regroupSpreads() {}
+    this._spreadMode = mode;
+    this.eventBus.dispatch('spreadmodechanged', {
+      source: this,
+      mode
+    });
+    this._updateSpreadMode(this._currentPageNumber);
+  }
+  _updateSpreadMode(pageNumber = null) {
+    if (!this.pdfDocument) {
+      return;
+    }
+    const viewer = this.viewer,
+          pages = this._pages;
+    viewer.textContent = '';
+    if (this._spreadMode === SpreadMode.NONE) {
+      for (let i = 0, iMax = pages.length; i < iMax; ++i) {
+        viewer.appendChild(pages[i].div);
+      }
+    } else {
+      const parity = this._spreadMode - 1;
+      let spread = null;
+      for (let i = 0, iMax = pages.length; i < iMax; ++i) {
+        if (spread === null) {
+          spread = document.createElement('div');
+          spread.className = 'spread';
+          viewer.appendChild(spread);
+        } else if (i % 2 === parity) {
+          spread = spread.cloneNode(false);
+          viewer.appendChild(spread);
+        }
+        spread.appendChild(pages[i].div);
+      }
+    }
+    if (!pageNumber) {
+      return;
+    }
+    this.scrollPageIntoView({ pageNumber });
+    this.update();
+  }
+  setSpreadMode(mode) {}
 }
 exports.BaseViewer = BaseViewer;
 exports.ScrollMode = ScrollMode;
 exports.SpreadMode = SpreadMode;
 
 /***/ }),
 /* 26 */
 /***/ (function(module, exports, __webpack_require__) {
@@ -8154,16 +8173,18 @@ class SecondaryToolbar {
   setPagesCount(pagesCount) {
     this.pagesCount = pagesCount;
     this._updateUIState();
   }
   reset() {
     this.pageNumber = 0;
     this.pagesCount = 0;
     this._updateUIState();
+    this.eventBus.dispatch('resetscrollmode', { source: this });
+    this.eventBus.dispatch('resetspreadmode', { source: this });
   }
   _updateUIState() {
     this.items.firstPage.disabled = this.pageNumber <= 1;
     this.items.lastPage.disabled = this.pageNumber >= this.pagesCount;
     this.items.pageRotateCw.disabled = this.pagesCount === 0;
     this.items.pageRotateCcw.disabled = this.pagesCount === 0;
   }
   _bindClickListeners() {
@@ -8194,49 +8215,61 @@ class SecondaryToolbar {
           break;
         case _pdf_cursor_tools.CursorTool.HAND:
           buttons.cursorHandToolButton.classList.add('toggled');
           break;
       }
     });
   }
   _bindScrollModeListener(buttons) {
-    this.eventBus.on('scrollmodechanged', function (evt) {
+    function scrollModeChanged(evt) {
       buttons.scrollVerticalButton.classList.remove('toggled');
       buttons.scrollHorizontalButton.classList.remove('toggled');
       buttons.scrollWrappedButton.classList.remove('toggled');
       switch (evt.mode) {
         case _base_viewer.ScrollMode.VERTICAL:
           buttons.scrollVerticalButton.classList.add('toggled');
           break;
         case _base_viewer.ScrollMode.HORIZONTAL:
           buttons.scrollHorizontalButton.classList.add('toggled');
           break;
         case _base_viewer.ScrollMode.WRAPPED:
           buttons.scrollWrappedButton.classList.add('toggled');
           break;
       }
+    }
+    this.eventBus.on('scrollmodechanged', scrollModeChanged);
+    this.eventBus.on('resetscrollmode', evt => {
+      if (evt.source === this) {
+        scrollModeChanged({ mode: _base_viewer.ScrollMode.VERTICAL });
+      }
     });
   }
   _bindSpreadModeListener(buttons) {
-    this.eventBus.on('spreadmodechanged', function (evt) {
+    function spreadModeChanged(evt) {
       buttons.spreadNoneButton.classList.remove('toggled');
       buttons.spreadOddButton.classList.remove('toggled');
       buttons.spreadEvenButton.classList.remove('toggled');
       switch (evt.mode) {
         case _base_viewer.SpreadMode.NONE:
           buttons.spreadNoneButton.classList.add('toggled');
           break;
         case _base_viewer.SpreadMode.ODD:
           buttons.spreadOddButton.classList.add('toggled');
           break;
         case _base_viewer.SpreadMode.EVEN:
           buttons.spreadEvenButton.classList.add('toggled');
           break;
       }
+    }
+    this.eventBus.on('spreadmodechanged', spreadModeChanged);
+    this.eventBus.on('resetspreadmode', evt => {
+      if (evt.source === this) {
+        spreadModeChanged({ mode: _base_viewer.SpreadMode.NONE });
+      }
     });
   }
   open() {
     if (this.opened) {
       return;
     }
     this.opened = true;
     this._setMaxHeight();
--- a/browser/locales/en-US/chrome/browser/downloads/downloads.properties
+++ b/browser/locales/en-US/chrome/browser/downloads/downloads.properties
@@ -87,20 +87,16 @@ sizeUnknown=Unknown size
 # that we use a wider space after the separator when it is followed by a number,
 # just to avoid visually confusing it with with a minus sign with some fonts.
 # If you use a different separator, this might not be necessary.  However, there
 # is usually no need to change the separator or the order of the substitutions,
 # even for right-to-left languages, unless the defaults are not suitable.
 statusSeparator=%1$S \u2014 %2$S
 statusSeparatorBeforeNumber=%1$S \u2014  %2$S
 
-fileExecutableSecurityWarning=“%S” is an executable file. Executable files may contain viruses or other malicious code that could harm your computer. Use caution when opening this file. Are you sure you want to launch “%S”?
-fileExecutableSecurityWarningTitle=Open Executable File?
-fileExecutableSecurityWarningDontAsk=Don’t ask me this again
-
 # LOCALIZATION NOTE (otherDownloads3):
 # This is displayed in an item at the bottom of the Downloads Panel when
 # there are more downloads than can fit in the list in the panel. Use a
 # semi-colon list of plural forms.
 # See: http://developer.mozilla.org/en/Localization_and_Plurals
 otherDownloads3=%1$S file downloading;%1$S files downloading
 
 # LOCALIZATION NOTE (showLabel, showMacLabel):
--- a/devtools/client/debugger/new/README.mozilla
+++ b/devtools/client/debugger/new/README.mozilla
@@ -1,13 +1,13 @@
 This is the debugger.html project output.
 See https://github.com/devtools-html/debugger.html
 
-Version 66
+Version 68
 
-Comparison: https://github.com/devtools-html/debugger.html/compare/release-65...release-66
+Comparison: https://github.com/devtools-html/debugger.html/compare/release-67...release-68
 
 Packages:
 - babel-plugin-transform-es2015-modules-commonjs @6.26.2
 - babel-preset-react @6.24.1
 - react @16.2.0
 - react-dom @16.2.0
 - webpack @3.11.0
--- a/devtools/client/debugger/new/dist/debugger.css
+++ b/devtools/client/debugger/new/dist/debugger.css
@@ -242,17 +242,16 @@ body {
   border-radius: 8px;
   background: transparent;
 }
 
 ::-webkit-scrollbar-thumb {
   border-radius: 8px;
   background: rgba(113, 113, 113, 0.5);
 }
-
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 menupopup {
   position: fixed;
   z-index: 10000;
   background: white;
--- a/devtools/client/debugger/new/dist/vendors.js
+++ b/devtools/client/debugger/new/dist/vendors.js
@@ -1,18 +1,18 @@
 (function webpackUniversalModuleDefinition(root, factory) {
 	if(typeof exports === 'object' && typeof module === 'object')
-		module.exports = factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories"));
+		module.exports = factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories"));
 	else if(typeof define === 'function' && define.amd)
-		define(["devtools/client/shared/vendor/react", "devtools/client/shared/vendor/react-dom", "Services", "devtools/shared/flags", "devtools/client/shared/vendor/react-prop-types", "devtools/client/shared/vendor/react-dom-factories"], factory);
+		define(["devtools/client/shared/vendor/react", "devtools/client/shared/vendor/lodash", "devtools/client/shared/vendor/react-dom", "Services", "devtools/shared/flags", "devtools/client/shared/vendor/react-prop-types", "devtools/client/shared/vendor/react-dom-factories"], factory);
 	else {
-		var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories")) : factory(root["devtools/client/shared/vendor/react"], root["devtools/client/shared/vendor/react-dom"], root["Services"], root["devtools/shared/flags"], root["devtools/client/shared/vendor/react-prop-types"], root["devtools/client/shared/vendor/react-dom-factories"]);
+		var a = typeof exports === 'object' ? factory(require("devtools/client/shared/vendor/react"), require("devtools/client/shared/vendor/lodash"), require("devtools/client/shared/vendor/react-dom"), require("Services"), require("devtools/shared/flags"), require("devtools/client/shared/vendor/react-prop-types"), require("devtools/client/shared/vendor/react-dom-factories")) : factory(root["devtools/client/shared/vendor/react"], root["devtools/client/shared/vendor/lodash"], root["devtools/client/shared/vendor/react-dom"], root["Services"], root["devtools/shared/flags"], root["devtools/client/shared/vendor/react-prop-types"], root["devtools/client/shared/vendor/react-dom-factories"]);
 		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
 	}
-})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_4__, __WEBPACK_EXTERNAL_MODULE_22__, __WEBPACK_EXTERNAL_MODULE_52__, __WEBPACK_EXTERNAL_MODULE_3642__, __WEBPACK_EXTERNAL_MODULE_3643__) {
+})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_4__, __WEBPACK_EXTERNAL_MODULE_22__, __WEBPACK_EXTERNAL_MODULE_52__, __WEBPACK_EXTERNAL_MODULE_3642__, __WEBPACK_EXTERNAL_MODULE_3643__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
 /******/
 /******/ 	// The require function
 /******/ 	function __webpack_require__(moduleId) {
 /******/
 /******/ 		// Check if module is in cache
@@ -77,102 +77,16 @@ return /******/ (function(modules) { // 
 
 /***/ 0:
 /***/ (function(module, exports) {
 
 module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
 
 /***/ }),
 
-/***/ 10:
-/***/ (function(module, exports, __webpack_require__) {
-
-var Symbol = __webpack_require__(7);
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Used to resolve the
- * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
- * of values.
- */
-var nativeObjectToString = objectProto.toString;
-
-/** Built-in value references. */
-var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
-
-/**
- * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
- *
- * @private
- * @param {*} value The value to query.
- * @returns {string} Returns the raw `toStringTag`.
- */
-function getRawTag(value) {
-  var isOwn = hasOwnProperty.call(value, symToStringTag),
-      tag = value[symToStringTag];
-
-  try {
-    value[symToStringTag] = undefined;
-    var unmasked = true;
-  } catch (e) {}
-
-  var result = nativeObjectToString.call(value);
-  if (unmasked) {
-    if (isOwn) {
-      value[symToStringTag] = tag;
-    } else {
-      delete value[symToStringTag];
-    }
-  }
-  return result;
-}
-
-module.exports = getRawTag;
-
-
-/***/ }),
-
-/***/ 100:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assocIndexOf = __webpack_require__(96);
-
-/**
- * Sets the list cache `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf ListCache
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the list cache instance.
- */
-function listCacheSet(key, value) {
-  var data = this.__data__,
-      index = assocIndexOf(data, key);
-
-  if (index < 0) {
-    ++this.size;
-    data.push([key, value]);
-  } else {
-    data[index][1] = value;
-  }
-  return this;
-}
-
-module.exports = listCacheSet;
-
-
-/***/ }),
-
 /***/ 1000:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 -2.5 34 32\"><path d=\"M19.314 15.987c0 1.321-1.071 2.392-2.392 2.392s-2.392-1.071-2.392-2.392c0-1.321 1.071-2.392 2.392-2.392s2.392 1.071 2.392 2.392z\"></path><path d=\"M16.922 24.783c1.878 1.826 3.729 2.906 5.221 2.906 0.489 0 0.952-0.103 1.337-0.334 1.337-0.772 1.826-2.701 1.363-5.453-0.077-0.489-0.18-0.977-0.309-1.492 0.514-0.154 0.977-0.309 1.44-0.463 2.598-1.003 4.038-2.392 4.038-3.909 0-1.543-1.44-2.932-4.038-3.909-0.463-0.18-0.926-0.334-1.44-0.463 0.129-0.514 0.232-1.003 0.309-1.492 0.437-2.803-0.051-4.758-1.389-5.53-0.386-0.231-0.849-0.334-1.337-0.334-1.466 0-3.344 1.080-5.221 2.906-1.852-1.826-3.704-2.906-5.195-2.906-0.489 0-0.952 0.103-1.337 0.334-1.337 0.772-1.826 2.701-1.363 5.453 0.077 0.489 0.18 0.977 0.309 1.492-0.514 0.154-0.977 0.309-1.44 0.463-2.598 1.003-4.038 2.392-4.038 3.909 0 1.543 1.44 2.932 4.038 3.909 0.463 0.18 0.926 0.334 1.44 0.463-0.129 0.514-0.232 1.003-0.309 1.492-0.437 2.752 0.051 4.707 1.363 5.453 0.386 0.232 0.849 0.334 1.337 0.334 1.492 0.051 3.344-1.029 5.221-2.829v0zM15.481 21.311c0.463 0.026 0.952 0.026 1.44 0.026s0.977 0 1.44-0.026c-0.463 0.617-0.952 1.183-1.44 1.723-0.489-0.54-0.977-1.106-1.44-1.723zM12.292 18.662c0.257 0.437 0.489 0.849 0.772 1.26-0.797-0.103-1.543-0.232-2.263-0.386 0.232-0.694 0.489-1.415 0.797-2.135 0.206 0.411 0.437 0.849 0.694 1.26zM10.8 12.463c0.72-0.154 1.466-0.283 2.263-0.386-0.257 0.412-0.514 0.823-0.772 1.26s-0.489 0.849-0.694 1.286c-0.334-0.746-0.592-1.466-0.797-2.161zM12.215 15.987c0.334-0.694 0.694-1.389 1.106-2.083 0.386-0.669 0.823-1.337 1.26-2.006 0.772-0.051 1.543-0.077 2.341-0.077 0.823 0 1.595 0.026 2.341 0.077 0.463 0.669 0.874 1.337 1.26 2.006 0.412 0.694 0.772 1.389 1.106 2.083-0.334 0.694-0.694 1.389-1.106 2.083-0.386 0.669-0.823 1.337-1.26 2.006-0.772 0.051-1.543 0.077-2.341 0.077-0.823 0-1.595-0.026-2.341-0.077-0.463-0.669-0.874-1.337-1.26-2.006-0.412-0.695-0.772-1.389-1.106-2.083v0zM22.272 14.598l-0.694-1.286c-0.257-0.437-0.489-0.849-0.772-1.26 0.797 0.103 1.543 0.232 2.263 0.386-0.231 0.72-0.489 1.44-0.797 2.161v0zM22.272 17.376c0.309 0.72 0.566 1.44 0.797 2.135-0.72 0.154-1.466 0.283-2.263 0.386 0.257-0.412 0.514-0.823 0.772-1.26 0.232-0.386 0.463-0.823 0.694-1.26v0zM22.863 26.301c-0.206 0.129-0.463 0.18-0.746 0.18-1.26 0-2.829-1.029-4.372-2.572 0.746-0.797 1.466-1.698 2.186-2.701 1.209-0.103 2.366-0.283 3.447-0.54 0.129 0.463 0.206 0.926 0.283 1.389 0.36 2.186 0.077 3.755-0.797 4.244zM24.201 12.746c2.881 0.823 4.604 2.083 4.604 3.241 0 1.003-1.183 2.006-3.266 2.804-0.412 0.154-0.874 0.309-1.337 0.437-0.334-1.055-0.746-2.135-1.26-3.241 0.514-1.106 0.952-2.186 1.26-3.241v0zM22.143 5.493c0.283 0 0.514 0.051 0.746 0.18 0.849 0.489 1.157 2.032 0.797 4.244-0.077 0.437-0.18 0.9-0.283 1.389-1.080-0.232-2.238-0.412-3.447-0.54-0.694-1.003-1.44-1.903-2.186-2.701 1.543-1.518 3.112-2.572 4.372-2.572zM18.362 10.663c-0.463-0.026-0.952-0.026-1.44-0.026s-0.977 0-1.44 0.026c0.463-0.617 0.952-1.183 1.44-1.723 0.489 0.54 0.977 1.132 1.44 1.723v0zM10.98 5.673c0.206-0.129 0.463-0.18 0.746-0.18 1.26 0 2.829 1.029 4.372 2.572-0.746 0.797-1.466 1.697-2.186 2.701-1.209 0.103-2.366 0.283-3.447 0.54-0.129-0.463-0.206-0.926-0.283-1.389-0.36-2.186-0.077-3.729 0.797-4.244v0zM9.643 19.228c-2.881-0.823-4.604-2.083-4.604-3.241 0-1.003 1.183-2.006 3.266-2.803 0.412-0.154 0.874-0.309 1.337-0.437 0.334 1.055 0.746 2.135 1.26 3.241-0.514 1.106-0.952 2.212-1.26 3.241zM10.183 22.057c0.077-0.437 0.18-0.9 0.283-1.389 1.080 0.232 2.238 0.412 3.447 0.54 0.694 1.003 1.44 1.903 2.186 2.701-1.543 1.517-3.112 2.572-4.372 2.572-0.283 0-0.514-0.051-0.746-0.18-0.875-0.489-1.157-2.058-0.797-4.244z\"></path></svg>"
 
 /***/ }),
 
 /***/ 1001:
@@ -198,102 +112,16 @@ module.exports = "<!-- This Source Code 
 
 /***/ 1004:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 128 128\" style=\"enable-background:new 0 0 128 128;\" xml:space=\"preserve\"><style type=\"text/css\"> .st0{fill:#C1272D;} .st1{fill:#EFCCA3;} .st2{fill:#ED1C24;} .st3{fill:#CCAC8D;} .st4{fill:#FFFFFF;} .st5{fill:#FF931E;} .st6{fill:#FFB81E;} .st7{fill:#56332B;} .st8{fill:#442823;} .st9{fill:#7F4A41;} .st10{fill:#331712;} .st11{fill:#FFCC66;} .st12{fill:#CCCCCC;} .st13{fill:#B3B3B3;} .st14{fill:#989898;} .st15{fill:#323232;} .st16{fill:#1E1E1E;} .st17{fill:#4C4C4C;} .st18{fill:#E6E6E6;} .st19{fill:#606060;} </style><g><path class=\"st1\" d=\"M107.4,50.9c-0.2-4.4,0.4-8.3-1.6-11.6c-4.8-8.2-16.8-13-40.8-13V27c0,0-0.5,0-0.5,0c0,0,0.5,0,0.5,0v-0.7 c-24,0-36.6,4.8-41.4,13.1c-1.9,3.4-1.7,7.2-2,11.6c-0.2,3.5-1.8,7.2-1.1,11.2c0.8,5.2,1.1,10.4,1.9,15.2c0.6,3.9,6,7.2,6.5,10.9 c1.4,10.2,12,14.9,36,14.9v0.8h-0.6h0.1H65v-0.8c24,0,34.2-4.7,35.5-14.9c0.5-3.8,5.5-7,6.1-10.9c0.8-4.8,1.1-10,1.9-15.2 C109.2,58.2,107.6,54.4,107.4,50.9z\"></path><path class=\"st3\" d=\"M64.6,54.5c4.3,0.1,7.3,2.8,10.1,5.3c3.3,2.9,8.9,4.9,11.2,7.4c2.3,2.5,5.3,5,6.4,8.9 c1.1,3.9,1.4,8.9,1.4,10.2c0,1.3,0.7,1,2.7,0c4.7-2.3,9.9-8.5,9.9-8.5c-0.6,3.9-5.7,7.4-6.2,11.1C98.9,99.1,89,104,64.5,104h-0.1h0 H65\"></path><path class=\"st3\" d=\"M80.4,46.7c0.9,3.1,4.1,13.6-2.1,10.1c0,0,2.6,1.5,4.2,7.2c1.7,5.7,5.8,6.4,5.8,6.4s6.7,1.3,11.7-3 c4.2-3.6,4.9-10,3.1-14.9c-1.8-4.8-5-6.3-9.7-7.3C88.7,44.1,79.3,43.2,80.4,46.7z\"></path><g><circle cx=\"92.3\" cy=\"58.1\" r=\"8.8\"></circle><circle class=\"st4\" cx=\"90\" cy=\"54.2\" r=\"2.3\"></circle></g><path class=\"st1\" d=\"M78.9,57.7c0,0,7.9,5.4,12.2,10.7c4.3,5.3,4.2,6.3,4.2,6.3l-3.1,1.4c0,0-4.4-8.3-9.8-11.4 c-5.5-3.1-6.1-5.7-6.1-5.7L78.9,57.7z\"></path><path class=\"st3\" d=\"M64.9,54.5c-4.3,0.1-7.5,2.8-10.4,5.3c-3.3,2.9-9.1,4.9-11.4,7.4c-2.3,2.5-5.4,5-6.5,8.9 c-1.1,3.9-1.5,8.9-1.5,10.2c0,1.3,0.2,1.4-2.7,0c-4.7-2.2-9.9-8.5-9.9-8.5c0.6,3.9,5.7,7.4,6.2,11.1C30.1,99.1,40,104,64.5,104h0.1 h0H65\"></path><path class=\"st7\" d=\"M88.1,71.4C83.3,65.5,75.6,60,64.9,60h-0.1h0c-10.7,0-18.4,5.5-23.2,11.4c-5,6.1-4.6,8.5-4.6,14.3 c0,21,7.4,15,12.3,17.6c5,2.5,10.2,1.7,15.5,1.7h0h0.1c5.4,0,10.5,0.7,15.5-1.8c4.9-2.5,12.3,3.7,12.3-17.3 C92.8,80.1,93.1,77.5,88.1,71.4z\"></path><path class=\"st8\" d=\"M64.4,65.2c0,0-0.7,9.7-2.1,11.6l2.6-0.6L64.4,65.2z\"></path><path class=\"st8\" d=\"M65.1,65.2c0,0,0.7,9.7,2.1,11.6l-2.6-0.6L65.1,65.2z\"></path><path class=\"st7\" d=\"M56.7,62.9c-1-2.3,2.6-6,8.3-6.1c5.7,0,9.3,3.7,8.3,6.1c-1,2.4-4.6,3.1-8.3,3.2C61.4,66,57.7,65.3,56.7,62.9z\"></path><path d=\"M65,65.2c0-0.4,3.4-0.5,5.2-1.7c0,0-3.7,1.2-4.5,0.7c-0.8-0.4-1-1.6-1-1.6s-0.3,1.2-0.9,1.6c-0.7,0.4-4.9-0.7-4.9-0.7 s5.6,1.4,5.6,1.7c0,0.3-0.1,1.3-0.1,2c0,2.5,0,8.7,0.4,9.2c0.6,0.9,0.4-6.7,0.4-9.2C65.1,66.4,65.1,65.6,65,65.2z\"></path><path class=\"st9\" d=\"M65.2,78.6c1.7,0,4.7,1.2,7.4,3.1c-2.6-2.9-5.7-4.9-7.4-4.9c-1.8,0-5.6,2.2-8.3,5.4 C59.7,80,63.3,78.6,65.2,78.6z\"></path><path class=\"st8\" d=\"M64.5,96.3c-3.8,0-7.5-1.2-10.9-2.1c-0.7-0.2-1.4,0.3-2.1,0.1c-6.3-2-11.4-5.4-14.5-9.7c0,0.3,0,0.7,0,1 c0,21,7.4,15.1,12.3,17.6c5,2.5,10.2,1.7,15.5,1.7h0h0.1c5.4,0,10.5,0.7,15.5-1.8c4.9-2.5,12.3,3.6,12.3-17.4c0-0.8,0-1.6,0.1-2.3 c-2.9,4.7-8.2,8.4-14.8,10.6c-0.6,0.2-2-0.3-2.6-0.2C71.8,95,68.6,96.3,64.5,96.3z\"></path><path class=\"st8\" d=\"M55,85c0,0-2.5,7.5-0.8,10.8l-2.3-1C51.9,94.8,53.6,87.2,55,85z\"></path><path class=\"st8\" d=\"M74.8,85c0,0,2.5,7.5,0.8,10.8l2.3-1C77.9,94.8,76.1,87.2,74.8,85z\"></path><path class=\"st3\" d=\"M48.6,46.7c-0.9,3.1-4.1,13.6,2.1,10.1c0,0-2.6,1.5-4.2,7.2s-5.8,6.4-5.8,6.4s-6.7,1.3-11.7-3 c-4.2-3.6-4.9-10-3.1-14.9s5-6.3,9.7-7.3C40.3,44.1,49.6,43.2,48.6,46.7z\"></path><path d=\"M64.9,76.8c2.7,0,11.1,5.8,11.2,12.9c0-0.1,0-0.2,0-0.4c0-7.4-6.8-13.3-11.2-13.3c-4.4,0-11.2,6-11.2,13.3 c0,0.1,0,0.2,0,0.4C53.8,82.6,62.2,76.8,64.9,76.8z\"></path><g><ellipse transform=\"matrix(0.9683 -0.2497 0.2497 0.9683 -13.2339 18.6065)\" class=\"st10\" cx=\"66.7\" cy=\"61.5\" rx=\"0.8\" ry=\"1.5\"></ellipse><ellipse transform=\"matrix(0.9551 0.2963 -0.2963 0.9551 21.0115 -15.7209)\" class=\"st10\" cx=\"62.4\" cy=\"61.5\" rx=\"0.8\" ry=\"1.5\"></ellipse></g><g><circle cx=\"37.2\" cy=\"58.1\" r=\"8.8\"></circle><circle class=\"st4\" cx=\"39.5\" cy=\"54.2\" r=\"2.3\"></circle></g><g><path class=\"st9\" d=\"M67.5,58.2c0-0.1-2.3,1-2.9,1.1c-0.6-0.1-2.9-1.2-2.9-1.1c0,0,1.9,0,2.9,0C65.6,58.2,67.5,58.2,67.5,58.2z\"></path></g><path class=\"st1\" d=\"M50,57.7c0,0-7.9,5.4-12.2,10.7c-4.3,5.3-4.2,6.3-4.2,6.3l3.1,1.4c0,0,4.4-8.3,9.8-11.4s6.1-5.7,6.1-5.7 L50,57.7z\"></path><path class=\"st3\" d=\"M32.7,41.7c0,0-2.7,7.4-8.7,10.5C24,52.2,33.4,51.1,32.7,41.7z\"></path><path class=\"st3\" d=\"M95.8,41.7c0,0,2.7,7.4,8.7,10.5C104.5,52.2,95.1,51.1,95.8,41.7z\"></path><path class=\"st3\" d=\"M78.7,55.5c0,0-5.9-6.2-13.8-6.4l0,0c-0.1,0,0.2,0,0.1,0c-0.1,0,0.1,0,0.1,0v0c-8,0.2-13.8,6.4-13.8,6.4 c6.9-4.8,12.8-4.7,13.8-4.7v0c0,0,0,0,0,0c0,0,0,0,0,0v0C65,50.8,71.8,50.7,78.7,55.5z\"></path><path class=\"st3\" d=\"M71.8,42.5c0,0-3-4.2-7-4.3l0,0c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0v0c-3,0.1-6.9,4.3-6.9,4.3 c3.4-3.3,6.9-3.2,6.9-3.2v0c0,0,0,0,0,0c0,0,0,0,0,0v0C65,39.3,68.3,39.2,71.8,42.5z\"></path><path class=\"st3\" d=\"M37.2,73.2c0,0-4.7,2.3-8.1,0.9l0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0v0c-3-1.7-4.5-6.8-4.5-6.8 S27.5,76.3,37.2,73.2z\"></path><path class=\"st3\" d=\"M92,73.2c0,0,4.7,2.3,8.1,0.9l0,0c0,0,0,0,0,0c0,0,0,0,0,0v0c4-1.7,4.6-6.8,4.6-6.8S101.7,76.3,92,73.2z\"></path><g><path class=\"st3\" d=\"M42.6,41.2c2.6-0.5,6.9-0.6,10.3,0.5c4.3,1.5,0.8,7,1.7,7.3c0.9,0.3,2.1-3.8,10.1-3.4c8.1,0.4,9,4,10.1,3.4 s-1.1-10,11-7.8c0,0-12.7-3.4-12.1,5.8c0,0-7.3-5.6-17.5-0.6C56.3,46.4,58.9,37.8,42.6,41.2z\"></path></g><path class=\"st3\" d=\"M86.9,41.2c0.2,0,0.3,0.1,0.4,0.1C87.4,41.3,87.2,41.2,86.9,41.2z\"></path><path class=\"st3\" d=\"M86.9,41.2C86.9,41.2,86.9,41.2,86.9,41.2C86.9,41.2,86.9,41.2,86.9,41.2z\"></path><path class=\"st3\" d=\"M39.1,28.9c0,0-10.8,13.6-12.4,18.8c-1.6,5.3-2.8,27-4.2,30.1l-5-21.4l9.2-22.3L39.1,28.9z\"></path><path class=\"st3\" d=\"M89.9,28.9c0,0,10.8,13.6,12.4,18.8c1.6,5.3,2.8,27,4.2,30.1l5-21.4l-9.2-22.3L89.9,28.9z\"></path><path class=\"st7\" d=\"M89.4,28.9c0,0,11.6,9.7,15,20.9c3.4,11.2,2,24.8,4.6,26.5c3.7,2.4,7.9-11.9,9.3-13.4c2.2-2.4,9.5-8.5,10-9.6 c0.5-1.1-14.8-17.8-21.5-21.1C98.7,28.4,88.7,28.1,89.4,28.9z\"></path><path class=\"st8\" d=\"M99.3,34.9c0,0,13.7,17.5,13.5,39.3l5.5-11.2C118.2,63,113.4,48.7,99.3,34.9z\"></path><path class=\"st7\" d=\"M39.1,28.9c0,0-11.6,9.7-15,20.9s-2,24.8-4.6,26.5c-3.7,2.4-7.9-11.9-9.3-13.4c-2.2-2.4-9.5-8.5-10-9.6 c-0.5-1.1,14.8-17.8,21.5-21.1C29.8,28.4,39.8,28.1,39.1,28.9z\"></path><path class=\"st8\" d=\"M29.2,34.9c0,0-13.7,17.5-13.5,39.3L10.3,63C10.3,63,15.1,48.7,29.2,34.9z\"></path><path class=\"st3\" d=\"M21.8,74.6c0,0,1,5.4,2.6,7.1s0.5-1.3,0.5-1.3s-1.7-0.9-1.4-7.8S21.8,74.6,21.8,74.6z\"></path><path class=\"st3\" d=\"M107.1,74.6c0,0-1,5.4-2.6,7.1s-0.5-1.3-0.5-1.3s1.7-0.9,1.4-7.8S107.1,74.6,107.1,74.6z\"></path><g><circle class=\"st8\" cx=\"54.5\" cy=\"70.5\" r=\"0.8\"></circle><circle class=\"st8\" cx=\"49.9\" cy=\"75.3\" r=\"0.8\"></circle><circle class=\"st8\" cx=\"48.4\" cy=\"70.5\" r=\"0.8\"></circle></g><g><circle class=\"st8\" cx=\"74\" cy=\"70.5\" r=\"0.8\"></circle><circle class=\"st8\" cx=\"78.6\" cy=\"75.3\" r=\"0.8\"></circle><circle class=\"st8\" cx=\"80.1\" cy=\"70.5\" r=\"0.8\"></circle></g></g></svg>"
 
 /***/ }),
 
-/***/ 101:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getNative = __webpack_require__(81),
-    root = __webpack_require__(8);
-
-/* Built-in method references that are verified to be native. */
-var Map = getNative(root, 'Map');
-
-module.exports = Map;
-
-
-/***/ }),
-
-/***/ 102:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getMapData = __webpack_require__(103);
-
-/**
- * Removes `key` and its value from the map.
- *
- * @private
- * @name delete
- * @memberOf MapCache
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function mapCacheDelete(key) {
-  var result = getMapData(this, key)['delete'](key);
-  this.size -= result ? 1 : 0;
-  return result;
-}
-
-module.exports = mapCacheDelete;
-
-
-/***/ }),
-
-/***/ 103:
-/***/ (function(module, exports, __webpack_require__) {
-
-var isKeyable = __webpack_require__(104);
-
-/**
- * Gets the data for `map`.
- *
- * @private
- * @param {Object} map The map to query.
- * @param {string} key The reference key.
- * @returns {*} Returns the map data.
- */
-function getMapData(map, key) {
-  var data = map.__data__;
-  return isKeyable(key)
-    ? data[typeof key == 'string' ? 'string' : 'hash']
-    : data.map;
-}
-
-module.exports = getMapData;
-
-
-/***/ }),
-
-/***/ 104:
-/***/ (function(module, exports) {
-
-/**
- * Checks if `value` is suitable for use as unique object key.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
- */
-function isKeyable(value) {
-  var type = typeof value;
-  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
-    ? (value !== '__proto__')
-    : (value === null);
-}
-
-module.exports = isKeyable;
-
-
-/***/ }),
-
 /***/ 1043:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" id=\"svg2\" viewBox=\"0 0 34 34\"><defs id=\"defs4\"><linearGradient id=\"linearGradient4275\"><stop id=\"stop4277\" offset=\"0\" style=\"stop-color:#006e00;stop-opacity:1\"></stop><stop style=\"stop-color:#00cc00;stop-opacity:1;\" offset=\"0.55349338\" id=\"stop4283\"></stop><stop id=\"stop4279\" offset=\"1\" style=\"stop-color:#eeff2a;stop-opacity:1\"></stop></linearGradient><linearGradient gradientTransform=\"matrix(0.03267513,0,0,0.03267513,5.555801,1018.6805)\" gradientUnits=\"userSpaceOnUse\" y2=\"275.13159\" x2=\"162.84953\" y1=\"823.703\" x1=\"555.89331\" id=\"linearGradient4281\" xlink:href=\"#linearGradient4275\"></linearGradient></defs><g transform=\"translate(0,-1018.3622)\" id=\"layer1\"><path id=\"path4136\" d=\"m 13.661978,1019.0545 c -9.6447445,1.1926 -10.316754,13.2244 -4.2596149,18.1959 6.0571409,4.9714 13.9697969,9.3171 10.7466029,14.4295 9.372821,-1.0092 10.165143,-10.5469 5.793842,-15.3419 -4.371301,-4.7949 -17.4582341,-10.442 -12.28083,-17.2835 z\" style=\"opacity:1;fill:url(#linearGradient4281);fill-opacity:1;stroke:#000080;stroke-width:0.29986507;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1\"></path></g></svg>"
 
 /***/ }),
 
 /***/ 1044:
@@ -305,255 +133,16 @@ module.exports = "<!-- This Source Code 
 
 /***/ 1045:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 14 5\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><desc>Created with Sketch.</desc><defs></defs><g id=\"Symbols\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" stroke-linecap=\"square\"><g id=\"outline\" transform=\"translate(0.000000, -2.000000)\" stroke=\"#DDE1E5\"><path d=\"M1.25,2.25 L1.25,2.75\" id=\"Line\" transform=\"translate(1.250000, 2.500000) rotate(90.000000) translate(-1.250000, -2.500000) \"></path><path d=\"M1.25,4.25 L1.25,4.75\" id=\"Line\" transform=\"translate(1.250000, 4.500000) rotate(90.000000) translate(-1.250000, -4.500000) \"></path><path d=\"M8.5,-3.5 L8.5,6.5\" id=\"Line\" transform=\"translate(8.000000, 2.000000) rotate(90.000000) translate(-8.000000, -2.000000) \"></path><path d=\"M8.5,-0.5 L8.5,9.5\" id=\"Line\" transform=\"translate(8.500000, 4.500000) rotate(90.000000) translate(-8.500000, -4.500000) \"></path><path d=\"M1.25,6.25 L1.25,6.75\" id=\"Line\" transform=\"translate(1.250000, 6.500000) rotate(90.000000) translate(-1.250000, -6.500000) \"></path><path d=\"M8.5,1.5 L8.5,11.5\" id=\"Line\" transform=\"translate(8.500000, 6.500000) rotate(90.000000) translate(-8.500000, -6.500000) \"></path></g></g></svg>"
 
 /***/ }),
 
-/***/ 105:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getMapData = __webpack_require__(103);
-
-/**
- * Gets the map value for `key`.
- *
- * @private
- * @name get
- * @memberOf MapCache
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function mapCacheGet(key) {
-  return getMapData(this, key).get(key);
-}
-
-module.exports = mapCacheGet;
-
-
-/***/ }),
-
-/***/ 106:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getMapData = __webpack_require__(103);
-
-/**
- * Checks if a map value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf MapCache
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function mapCacheHas(key) {
-  return getMapData(this, key).has(key);
-}
-
-module.exports = mapCacheHas;
-
-
-/***/ }),
-
-/***/ 107:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getMapData = __webpack_require__(103);
-
-/**
- * Sets the map `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf MapCache
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the map cache instance.
- */
-function mapCacheSet(key, value) {
-  var data = getMapData(this, key),
-      size = data.size;
-
-  data.set(key, value);
-  this.size += data.size == size ? 0 : 1;
-  return this;
-}
-
-module.exports = mapCacheSet;
-
-
-/***/ }),
-
-/***/ 108:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseToString = __webpack_require__(109);
-
-/**
- * Converts `value` to a string. An empty string is returned for `null`
- * and `undefined` values. The sign of `-0` is preserved.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to convert.
- * @returns {string} Returns the converted string.
- * @example
- *
- * _.toString(null);
- * // => ''
- *
- * _.toString(-0);
- * // => '-0'
- *
- * _.toString([1, 2, 3]);
- * // => '1,2,3'
- */
-function toString(value) {
-  return value == null ? '' : baseToString(value);
-}
-
-module.exports = toString;
-
-
-/***/ }),
-
-/***/ 109:
-/***/ (function(module, exports, __webpack_require__) {
-
-var Symbol = __webpack_require__(7),
-    arrayMap = __webpack_require__(110),
-    isArray = __webpack_require__(70),
-    isSymbol = __webpack_require__(72);
-
-/** Used as references for various `Number` constants. */
-var INFINITY = 1 / 0;
-
-/** Used to convert symbols to primitives and strings. */
-var symbolProto = Symbol ? Symbol.prototype : undefined,
-    symbolToString = symbolProto ? symbolProto.toString : undefined;
-
-/**
- * The base implementation of `_.toString` which doesn't convert nullish
- * values to empty strings.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- */
-function baseToString(value) {
-  // Exit early for strings to avoid a performance hit in some environments.
-  if (typeof value == 'string') {
-    return value;
-  }
-  if (isArray(value)) {
-    // Recursively convert values (susceptible to call stack limits).
-    return arrayMap(value, baseToString) + '';
-  }
-  if (isSymbol(value)) {
-    return symbolToString ? symbolToString.call(value) : '';
-  }
-  var result = (value + '');
-  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
-}
-
-module.exports = baseToString;
-
-
-/***/ }),
-
-/***/ 11:
-/***/ (function(module, exports) {
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/**
- * Used to resolve the
- * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
- * of values.
- */
-var nativeObjectToString = objectProto.toString;
-
-/**
- * Converts `value` to a string using `Object.prototype.toString`.
- *
- * @private
- * @param {*} value The value to convert.
- * @returns {string} Returns the converted string.
- */
-function objectToString(value) {
-  return nativeObjectToString.call(value);
-}
-
-module.exports = objectToString;
-
-
-/***/ }),
-
-/***/ 110:
-/***/ (function(module, exports) {
-
-/**
- * A specialized version of `_.map` for arrays without support for iteratee
- * shorthands.
- *
- * @private
- * @param {Array} [array] The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns the new mapped array.
- */
-function arrayMap(array, iteratee) {
-  var index = -1,
-      length = array == null ? 0 : array.length,
-      result = Array(length);
-
-  while (++index < length) {
-    result[index] = iteratee(array[index], index, array);
-  }
-  return result;
-}
-
-module.exports = arrayMap;
-
-
-/***/ }),
-
-/***/ 111:
-/***/ (function(module, exports, __webpack_require__) {
-
-var isSymbol = __webpack_require__(72);
-
-/** Used as references for various `Number` constants. */
-var INFINITY = 1 / 0;
-
-/**
- * Converts `value` to a string key if it's not a string or symbol.
- *
- * @private
- * @param {*} value The value to inspect.
- * @returns {string|symbol} Returns the key.
- */
-function toKey(value) {
-  if (typeof value == 'string' || isSymbol(value)) {
-    return value;
-  }
-  var result = (value + '');
-  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
-}
-
-module.exports = toKey;
-
-
-/***/ }),
-
 /***/ 1117:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\"><rect fill=\"#002f42\" width=\"16\" x=\"0\" y=\"28\" height=\"4\"></rect><rect fill=\"#0072b1\" width=\"16\" x=\"16\" y=\"28\" height=\"4\"></rect></svg>"
 
 /***/ }),
 
 /***/ 1118:
@@ -565,229 +154,16 @@ module.exports = "<!-- This Source Code 
 
 /***/ 1119:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0.1 31.4 256 244.5\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" preserveAspectRatio=\"xMinYMin meet\"><path fill=\"#FFF\" d=\"M57.9 219.3l.6-1.5.1-.2c.5-1.2 1-2.5 1.5-3.7.6-1.6 1.2-3.3 1.8-4.9.4-.9.7-1.8 1-2.8.8-2.2 1.9-5.1 3.2-7.9.8-1.7 1.4-2.9 2.1-4 .8-1.3 1.6-2.5 2.5-3.7l.7-1 1.1-.7c.1-.1.3-.2.5-.3.5-.3 1.1-.5 1.5-.7.7-.3 1.6-.6 2.6-.9 1.4-.4 3-.8 4.9-1.2 2.8-.6 5.8-1.2 9.6-1.8 5.7-.9 11.8-1.7 19.1-2.5 12.9-1.4 25.8-2.4 38.2-3 6.6-.3 11.6-.4 16.3-.4h3c3.1.1 6.7.2 10 .7 1.2.2 2.3.4 3.1.7.3.1.6.2.7.3l1 .4.8.7.9.9c1.1 1.1 2.3 2.4 3.5 3.9 3.8 4.8 7.2 10.6 10.2 17.2 2.9 6.4 4.7 12.1 5.8 17.7l1.5 7.9h-18.4l-1.1-5.3c-1.2-5.6-16.3-20.4-23.8-23.3-.8-.3-4-1.2-13.9-1.2-20.4 0-49.2 3.6-53.3 4.5-4.9 2.3-12.4 11.9-16.7 21.5l-1.8 3.9\"></path><path fill=\"#BA8449\" d=\"M182.9 190.1c-.9-1.2-1.9-2.3-3-3.3l-.7-.7s-.1 0-.2-.1c-.5-.2-1.2-.3-1.9-.4-2.9-.4-6-.5-9.1-.6-6.3-.1-12.6.1-18.9.4-12.6.6-25.3 1.6-37.8 3-6.3.7-12.6 1.5-18.8 2.5-3.1.5-6.2 1-9.2 1.7-1.5.3-3 .7-4.4 1.1-.7.2-1.4.4-2 .7-.3.1-.6.2-.7.4 0 0-.1 0-.1.1-.7 1-1.4 2-2.1 3.1-.7 1.1-1.2 2.3-1.8 3.5-1.1 2.4-2.1 4.9-3 7.4s-1.9 5.1-2.8 7.7c-.5 1.3-1 2.6-1.6 3.9-.2.6-.5 1.2-.8 1.8h8.5c4.6-10.3 13.3-22.1 20.5-25 2-.8 34.2-4.8 55.5-4.8 7.9 0 13.3.6 16.3 1.7 8.7 3.4 26.1 19.5 27.9 28.2h4.9c-1-5.5-3-10.9-5.3-16.1-2.6-6-5.7-11.5-9.4-16.2\"></path><path fill=\"#FFF\" d=\"M179.1 185.9z\"></path><path fill=\"#BA8449\" d=\"M179.1 185.9z\"></path><path fill=\"#FFF\" d=\"M192.1 228.6l-1-5.4c-.9-4.5-2.4-9.3-4.8-14.6-2.6-5.6-5.4-10.5-8.6-14.4-.6-.8-1.2-1.5-1.8-2.1-2.5-.4-5.4-.4-8-.5h-2.8c-4.5 0-9.3.1-15.7.4-12.2.6-24.7 1.6-37.4 3-7.1.8-13 1.6-18.4 2.4-3.5.5-6.3 1.1-8.8 1.6-1.6.4-2.8.7-3.9 1-.2 0-.3.1-.4.1-.2.4-.5.7-.7 1.1-.5.8-.9 1.7-1.6 2.9-1.1 2.3-2 4.7-2.8 6.8-.4.9-.7 1.8-1 2.7-.6 1.7-1.2 3.4-1.9 5.1-.5 1.3-1.1 2.6-1.6 4l-.1.2c-.2.6-.5 1.2-.7 1.7l-1.8 4H56.6l-1.7-.8-.2-.1c-4-2.3-4-5.7-3.9-7.1v-.3l.2-.9.3-1.1c.2-.7.4-1.5.6-2.2.4-1.5.9-2.9 1.4-4.3.9-2.6 2-5.4 3.3-8.4 1.4-3.1 2.7-5.8 4.2-8.3.7-1.3 1.5-2.6 2.5-4.1.9-1.4 1.9-2.8 2.9-4.1.9-1.1 1.7-1.8 2.3-2.2h.1c.6-.5 1.2-.8 1.5-.9.9-.5 1.6-.8 2.1-1 1.2-.5 2.3-.8 3.2-1.1 2-.6 3.9-1 5.3-1.3 2.9-.6 6-1.2 9.9-1.8 5.8-.9 11.9-1.6 19.4-2.4 13-1.3 26-2.3 38.6-2.8 6-.2 10.7-.4 15-.4h4.6c3.2.1 6.8.2 10.7.8h.1c.9.2 2.3.4 3.9.9h.1c.4.2 1 .4 1.7.7.5.3.9.5 1.2.7l.5.4.4.3.4.4 1.1 1.1c1.3 1.3 2.5 2.7 3.8 4.4 4 5.2 7.5 11.2 10.7 18.3 1.5 3.3 2.8 6.6 3.8 9.8 1.1 3.5 1.9 6.8 2.5 10l1.2 7.7h-18.2v.1z\"></path><path fill=\"#FFF\" d=\"M64.3 228.6l4.4-9.5c3.7-7.9 12.6-22.4 22.5-26.5l.2-.1c3.3-1.2 36.7-5.1 57.1-5.1 11.4 0 15.7 1.1 17.9 2 10.3 4 28.2 20.9 30.6 30.9l2 8.2H64.3z\"></path><path fill=\"#FFF\" d=\"M185.4 228.6l-1.2-5.1c-1.1-4.7-15.2-18.8-22.5-21.7-.7-.3-3.6-1.1-13.2-1.1-19.6 0-48 3.5-52.6 4.4-3.8 1.9-10.7 10-15.2 19.6l-1.8 3.8H62.3l4.2-9.3c4.9-11 14.6-24.6 24.1-28.4 3.7-1.5 37.5-5.3 58-5.3 8.9 0 14.9.7 18.6 2.1 10.3 4 29.6 21.4 32 33l1.6 8h-15.4z\"></path><path fill=\"#FFF\" d=\"M193.1 228.6l-1.9-1.8c-7.2-6.7-9.2-20.6-7-26.3 1.5-3.8 4.7-5.1 7.1-5.1.7 0 1.3.1 1.9.3 1.3-.1 4.3-2.6 5.2-4 1.4-2.6 4.1-4.2 7.4-4.2 4.9 0 12.9 3.9 15.5 7.6 1.5 2.1 1.9 4.6 1.1 6.8-.1.2-.2.6-.4 1.1-2.7 8.1-6.2 18-9 22.6l-1.9 3.1-18-.1z\"></path><path fill=\"#FFF\" d=\"M192.5 228.6l6.2-10.1c3-4.9 5.1-8.9 6.5-12-3.5 2.5-8.4 4-15.7 4.4l-.2-.2-.1.7c-4.3 0-7.8-3.5-8-7.8-.1-2.1.7-4.2 2.1-5.8 1.4-1.6 3.4-2.5 5.5-2.6 7.2-.3 8.1-2 9.4-4.5 1.8-3.4 5.7-5.4 10.8-5.4 1.3 0 2.6.1 3.8.4 6.3 1.4 10.4 6.2 10.7 12.4.3 6.3-3.2 15.5-10.2 27.3l-1.9 3.2h-18.9z\"></path><path fill=\"#FFF\" d=\"M218.8 208.9c-8.1 0-16.9-5.3-21.4-10.5-4.1-4.7-4.5-8.9-4.1-11.6.5-3.3 3.2-6.6 8.1-6.6.9 0 1.8.1 2.6.2.8-3.6 2.7-11.1 10.4-11.1h1.1c3.7.4 6.5 2.7 7.6 6.2 1.2-.6 2.6-1.1 4.2-1.1 2.4 0 4.7 1 6.4 2.8 2.7 2.9 3.3 6.9 1.6 10.7 1.8 1.1 3.2 2.8 3.8 5 .8 2.8.3 5.8-1.5 8.2-3.5 4.9-11.6 7.2-18 7.4-.4.4-.6.4-.8.4M210.8 44.2c-7.3 4.6-15.3 15.1-25.1 29.5-1.5 2.3-4 3.5-6.8 3.5-3.6 0-8.2-2.2-13.5-6.5-8.4-6.8-8.6-10.6-8.7-12.1-.2-4 2.8-7.4 7-7.8 8.1-.7 14.8-5.6 21.3-10.3 6.5-4.7 12.5-9 19.7-9 1.4 0 2.9.2 4.3.5\"></path><path fill=\"#FFF8EE\" d=\"M164.3 57.5c19.6-1.8 31.1-22.1 43-19-8 5-15.9 15-27 31.4-2.7 3.9-21.4-11.9-16-12.4\"></path><path fill=\"#FFF\" d=\"M37.3 48.2c4.9-4.5 11.5-6.8 19.6-6.8 7 0 15.3 1.7 24.6 5.1 2.5.9 5.8 1.1 8.3 1.1h3.7c2.3 0 7.2 0 9.3 4.5.7 1.7 1.6 5.2-1.1 9.3-3.3 5.1-12 10.5-20.4 10.5h-.4c-4.5-.1-8.7-2.5-13.6-5.2-6.1-3.4-13-7.3-21.2-7.3-1.1 0-2.3.1-3.4.2M188.1 96.7c-3.6 0-10.4-1.5-14.7-11.7-2.4-5.4-3.2-11.5-3.2-14.9 0-7 3.7-8.9 6-9.4 1.6-1.6 4.6-5.7 6.8-8.8 9.1-12.4 15.7-20.5 23.4-20.5 1.3 0 2.5.2 3.7.7 10.3 4.1 15.3 12.8 13.6 23.8-1.2 8.1-6.3 17.7-13.8 26.5-3.5 4.1-12.6 13.7-20.7 14.3h-1.1\"></path><path fill=\"#FFF\" d=\"M69.9 100.5c-.9 0-1.8 0-2.6-.2-12.8-2.1-28.8-15-34.8-28.3-4.1-9.1-2.3-15.3 0-18.9 3.7-5.9 9.2-9 16-9 8.2 0 16.4 4.5 23.6 8.4 2.8 1.5 6.8 3.7 8.5 4.1.6-.2 1.2-.3 1.9-.3 2.6 0 5 1.4 6.4 3.8 3.3 5.8 1.3 21.4-3.9 30.4-3.6 6.6-9 10-15.1 10z\"></path><path fill=\"#FFF\" d=\"M114.5 212.1c-30 0-59.7-14.7-69.6-25.4-10.3-11.1-14-23.7-11.2-37.5 2.4-11.3 8.7-21.4 14.2-30.4 3.8-6.2 7.4-12 8.4-16.2 12.2-53.9 42.8-60.8 68.1-60.8 1.6 0 3.3 0 5.2.1 53.9 1.6 59.3 27.6 62.5 43.2.6 2.9 1.2 5.6 1.9 7.4 18.1 44.4 21.1 71 10 89-10.9 17.7-34.8 26.4-82.4 30.3-2.3.2-4.7.3-7.1.3z\"></path><path fill=\"#FFF\" d=\"M113.4 212.2c-30.6 0-58.9-15.2-68.4-25.5-10.3-11.1-14-23.7-11.2-37.5 2.4-11.3 8.7-21.4 14.2-30.4 3.8-6.2 7.4-12 8.4-16.2 12.2-53.9 42.8-60.8 68.1-60.8 1.6 0 3.3 0 5.2.1 53.9 1.6 59.3 27.6 62.5 43.2.6 2.9 1.2 5.6 1.9 7.4 17.8 43.7 20.7 70.1 9.8 88.1-12.5 20.7-41.9 27.4-82.1 31.2-2.8.3-5.6.4-8.4.4\"></path><path fill=\"#FFF\" d=\"M191.3 174.6c.4-.9.8-1.9 1.2-2.8 4.1-9.8 7.2-18.4 2.3-23.9-5.8-6.4-30.3-18-52.1-28.2-41.7-19.7-67.5-32.4-71.2-45-.9-3.2-.5-6.5 1.2-9.3C79.9 54.1 100 42 127.5 42h.8c25.9.2 44.7 7.7 56 22.1 9.6 12.2 11.7 26.5 13.3 36.9.5 3.5 1.2 8 1.9 9.2 19.6 33.7 10.6 58.6 3.5 70.3l-11.7-5.9z\"></path><path fill=\"#FFF\" d=\"M170.8 135.8c-10.1 0-27-2.5-32.8-8.1-4.6-4.4-6.3-11.7-8.1-18.8-.7-3-1.9-7.8-3-10h-.1c-.4 1.1-.9 2.5-1.3 3.6-2.7 7.6-6.5 18.1-14.4 23.8-3.4 2.5-15.7 4.7-25.2 4.7s-16.7-2-21.5-6.1c-6.9-5.8-12.1-16.5-15.6-31.8-.2-.1-.3-.2-.5-.3-1.6-1.1-3.7-2.4-4.8-4.7-1.8-3.6-1.1-10 .8-13.4 1.4-2.5 3.8-4.1 6.4-4.3h.9c1.4 0 2.8.2 4.4.5s3.5.6 5.1.6h.9c9.5-1.4 18.4-2 26.5-2 19.7 0 30.1 4 34 5.6.3.1.6.2.8.3 1.1.3 3.2.7 5.4.7.8 0 1.6 0 2.3-.2 8.9-1.4 17.4-2 25.2-2 20.8 0 31.8 4.7 36.6 6.8.4.2.8.4 1.1.4h.4c1.3 0 3.2-.4 4.8-.7 1.2-.3 2.4-.5 3.5-.7h.9c3.1 0 5.9 1.8 7.6 4.8 1.9 3.5 3.2 10.8.5 15-1.8 2.8-4.7 4.1-7.1 5.2-.3.1-.7.3-1 .5-.8 1.4-2.2 4.2-3.4 6.5-3.5 6.8-7.4 14.6-11 18.8-3.2 3.6-9.2 5.3-18.3 5.3\"></path><defs><path id=\"a\" d=\"M42.5 75H212v59.2H42.5z\"></path></defs><clipPath id=\"b\"><use xlink:href=\"#a\" overflow=\"visible\"></use></clipPath><g opacity=\".3\" clip-path=\"url(#b)\"><path fill=\"#FFF\" d=\"M166.778 134.181c-8 0-19.3-1.2-27.4-6.9-4.6-3.3-6.7-9.9-9.6-20.5-.8-3-2-7.2-2.9-9.3-.5 1.2-1.1 2.8-1.6 4.1-3 8.1-7.1 19.1-14.6 23.7-3.9 2.4-16 4.6-25.4 4.6-10.1 0-17.4-2.3-21.6-6.7-10.7-11.2-12.8-21.9-14.1-28.2-.2-.9-.4-2.1-.6-2.8-6.3-3.3-6.7-8.2-6.6-10.3.3-3.9 3.3-6.8 7-6.8 2.5 0 4.1 1.2 5.3 2 .1.1.2.2.4.2.1 0 .4.1.5.2 1.6.5 6.3 1.8 7.3 7.9.2 1.1 1.8 7.5 4.4 14.2 4.1 10.7 7 12.5 7.3 12.6 3.4 1.2 7.4 1.8 11.9 1.8 7.4 0 13.6-1.6 16.1-2.4 1.5-2.3 4.5-8.3 6.6-12.4 6.3-12.5 7.4-14.4 10.1-15.8 1.5-.8 3.3-1.2 5.6-1.2 3 0 7.3.7 9.3 1.6 4.6 2 7 8 12.4 23.5 1 2.8 2.2 6.4 3 8.2 4 1.9 13.1 3.2 22.6 3.2 2.7 0 4.7-.1 6-.2.9-1.9 2.2-4.6 3.3-6.9 7.6-16.2 8.8-18.1 10.7-19.6 3.3-2.5 9.1-4.2 12.4-4.2 4.4 0 6.8 2.9 7.4 5.7 1.1 5.8-4.6 8-6.5 8.7-.5.2-1.2.5-1.7.7-.7 1.2-2 3.8-3 5.9-8.2 16-10.9 20.4-14 22.3-3.8 2.1-13 3.1-20 3.1\"></path></g><defs><path id=\"c\" d=\"M45 70.7h33.4v16.2H45z\"></path></defs><clipPath id=\"d\"><use xlink:href=\"#c\" overflow=\"visible\"></use></clipPath><g opacity=\".3\" clip-path=\"url(#d)\"><path fill=\"#FFF\" d=\"M61.388 86.816c-1.2 0-3.5-.2-8.1-1.7-1.2-.4-2.3-.8-3-1.1-1.5-.6-5.4-2.1-5.4-6.7v-6.7h6.6c.9 0 1.5.2 2 .3 1.4.2 5.9.5 7.4.6l.9.1c1.2 0 4.9-.5 6.5-.7 2-.3 2.6-.4 3.4-.4h5.7l.9 5.6c.4 2.8-1.1 6.3-4.8 7.4-.2.1-.9.3-1.5.5-3.5 1.3-7 2.5-10 2.6-.2.2-.4.2-.6.2\"></path></g><defs><path id=\"e\" d=\"M181 79.3h25.4v17.2H181z\"></path></defs><clipPath id=\"f\"><use xlink:href=\"#e\" overflow=\"visible\"></use></clipPath><g opacity=\".3\" clip-path=\"url(#f)\"><path fill=\"#FFF\" d=\"M193.488 96.41c-2.2 0-4.4-.9-7.4-3-2.9-2-5.1-4-5.1-7.5v-6.7h6.5c.9 0 1.8.2 2.7.6.7.3 3.4 1.2 4.6 1.5.4 0 1.2-.2 2.8-.5.8-.2 1.3-.2 2-.2h5.7l.9 5.6c.4 2.7-.8 6.1-4.5 7.4l-1.2.6c-1.8.9-3.9 1.9-6 2.3-.2-.1-.6-.1-1-.1\"></path></g><path fill=\"#FFF\" d=\"M171.7 243.3h-24.6V222h24.6v21.3z\"></path><path fill=\"#BA8449\" d=\"M182.9 190.1c-.9-1.2-1.9-2.3-3-3.3l-.7-.7s-.1 0-.2-.1c-.5-.2-1.2-.3-1.9-.4-2.9-.4-6-.5-9.1-.6-6.3-.1-12.6.1-18.9.4-12.6.6-25.3 1.6-37.8 3-6.3.7-12.6 1.5-18.8 2.5-3.1.5-6.2 1-9.2 1.7-1.5.3-3 .7-4.4 1.1-.7.2-1.4.4-2 .7-.3.1-.6.2-.7.4 0 0-.1 0-.1.1-.7 1-1.4 2-2.1 3.1-.7 1.1-1.2 2.3-1.8 3.5-1.1 2.4-2.1 4.9-3 7.4s-1.9 5.1-2.8 7.7c-.5 1.3-1 2.6-1.6 3.9-.2.6-.5 1.2-.8 1.8h8.5c4.6-10.3 13.3-22.1 20.5-25 2-.8 34.2-4.8 55.5-4.8 7.9 0 13.3.6 16.3 1.7 8.7 3.4 26.1 19.5 27.9 28.2h4.9c-1-5.5-3-10.9-5.3-16.1-2.6-6-5.7-11.5-9.4-16.2M179.1 185.9z\"></path><path fill=\"#895B2E\" d=\"M179.1 185.9zm17.8 17.9c-2.7-6-5.8-11.7-9.9-16.9-1-1.3-2.1-2.6-3.3-3.8l-.9-.9-.2-.2-.1-.1-.2-.2c-.2-.1-.4-.2-.5-.3-.3-.2-.6-.3-.9-.4-1.1-.4-1.9-.5-2.8-.7-3.4-.5-6.6-.6-9.8-.7-6.5-.1-12.8 0-19.2.3-12.8.5-25.5 1.5-38.2 2.8-6.3.7-12.7 1.4-19.1 2.4-3.2.5-6.3 1-9.5 1.7-1.6.4-3.2.7-4.8 1.2-.8.2-1.6.5-2.5.9-.4.2-.9.4-1.4.7-.2.2-.5.3-.8.5-.3.2-.6.5-1 1-.9 1.1-1.8 2.4-2.6 3.6-.8 1.2-1.6 2.5-2.3 3.8-1.4 2.5-2.7 5.1-3.9 7.7-1.1 2.6-2.2 5.2-3.1 7.9-.5 1.3-.9 2.6-1.2 4-.2.7-.4 1.3-.6 2l-.3 1-.1.5c0 .1.2.2.6.5H64.2c.3-.6.5-1.2.8-1.8.5-1.3 1.1-2.6 1.6-3.8 1-2.6 1.9-5.1 2.8-7.7.9-2.5 1.9-5.1 3-7.4.6-1.2 1.2-2.3 1.8-3.5.7-1.1 1.3-2.1 2.1-3.1 0 0 .1 0 .1-.1.2-.1.5-.2.7-.4.6-.2 1.3-.5 2-.7 1.4-.4 2.9-.8 4.4-1.1 3-.7 6.1-1.2 9.2-1.7 6.2-1 12.5-1.8 18.8-2.5 12.6-1.4 25.2-2.4 37.8-3 6.3-.3 12.6-.5 18.9-.4 3.1.1 6.3.2 9.1.6.7.1 1.4.3 1.9.4.1 0 .2 0 .2.1l.7.7c1.1 1.1 2 2.2 3 3.3 3.7 4.7 6.8 10.2 9.4 15.8 2.3 5.2 4.3 10.6 5.3 16.1h5c-.5-3.1-1.3-6.1-2.2-9-1.2-3.1-2.4-6.1-3.7-9.1\"></path><path fill=\"#FFF8EE\" d=\"M164.1 195.7c-2.6-1-7.9-1.6-15.5-1.6-21.4 0-53 4-54.7 4.7-6.5 2.6-14.6 13.6-19.1 23.2h115.9c-1.9-7.5-18-22.9-26.6-26.3\"></path><path fill=\"#E5D0AE\" d=\"M164.8 193.8c-2.9-1.1-8.4-1.7-16.3-1.7-21.3 0-53.5 4-55.5 4.8-7.3 3-15.9 14.7-20.5 25h2.2c4.5-9.5 12.6-20.5 19.1-23.2 1.7-.7 33.3-4.7 54.7-4.7 7.6 0 12.9.5 15.5 1.6 8.6 3.3 24.7 18.8 26.6 26.3h2c-1.7-8.6-19.1-24.7-27.8-28.1\"></path><path fill=\"#BA8449\" d=\"M204.4 194.7c-1.2 2.5-7.5 8.9-12.8 7.4-2.8-.8-2.3 14 4.1 19.9h11.6c3.2-5.1 8.2-20.7 8.8-22.3.7-1.9-10.5-7.5-11.7-5\"></path><path fill=\"#895B2E\" d=\"M216.7 198.4c-.2-3.2-2.1-5.5-5.5-6.3-2.7-.6-6.3-.1-7.2 1.6-1.8 3.4-4 7.5-14.9 8.1-.7 0-1.3.7-1.3 1.4s.7 1.3 1.4 1.3c11.4-.5 14.7-4.9 17.1-9.4.5-.4 3.2-.9 5.4 0 1.6.7 2.3 1.8 2.4 3.5.3 6.2-6.2 17.7-9.7 23.5h3.1c3.9-6.8 9.5-17.3 9.2-23.7\"></path><defs><path id=\"g\" d=\"M193.5 196.5H217v27.3h-23.5z\"></path></defs><clipPath id=\"h\"><use xlink:href=\"#g\" overflow=\"visible\"></use></clipPath><g opacity=\".15\" clip-path=\"url(#h)\"><path fill=\"#E3AB5E\" d=\"M194.235 222.3c7.1-1.7 13.4-8.8 13.9-18.9.1-1.9-3.8-5.5-3.8-6.5s11.9.2 12.5 3c.5 2.8-7.4 19.7-10.1 22.5-2.6 2.7-16.7.9-12.5-.1\"></path></g><path fill=\"#FCD4C3\" d=\"M199.8 187.8c-.9 6.2 11.2 14.7 19.4 14.5 6.8-.2 14.5-3.4 13.4-7.2-1.1-3.9-7.7.7-8.3-2-.5-2.6 7.7-7.5 4.4-11.1-3.1-3.3-6.7 5.2-10.3 4-3.6-1.2.7-9.5-3.8-10-5.3-.5-3.3 11.3-7.3 11.5-2.8.3-7.2-1.7-7.5.3\"></path><path fill=\"none\" stroke=\"#F8A38F\" stroke-width=\"2\" stroke-miterlimit=\"10\" d=\"M199.8 187.8c-.9 6.2 11.2 14.7 19.4 14.5 6.8-.2 14.5-3.4 13.4-7.2-1.1-3.9-7.7.7-8.3-2-.5-2.6 7.7-7.5 4.4-11.1-3.1-3.3-6.7 5.2-10.3 4-3.6-1.2.7-9.5-3.8-10-5.3-.5-3.3 11.3-7.3 11.5-2.8.3-7.2-1.7-7.5.3z\"></path><defs><path id=\"i\" d=\"M203.2 182.8h7.8v6.4h-7.8z\"></path></defs><clipPath id=\"j\"><use xlink:href=\"#i\" overflow=\"visible\"></use></clipPath><g opacity=\".5\" clip-path=\"url(#j)\"><path fill=\"#FCD4C3\" d=\"M203.238 187.742c1.3 1 6 2.3 6.7.6.8-1.7 1.4-5.1.9-5.6-.4 1.6-.9 4.6-2.6 5.3-1.3.5-4.1-.1-5-.3\"></path></g><defs><path id=\"k\" d=\"M215.9 181.2h7.7v7.2h-7.7z\"></path></defs><clipPath id=\"l\"><use xlink:href=\"#k\" overflow=\"visible\"></use></clipPath><g opacity=\".5\" clip-path=\"url(#l)\"><path fill=\"#FCD4C3\" d=\"M216.159 181.142c-.2 1.1-1.1 6.3 1.6 7 2.3.6 4-.8 5.8-3.7-1 .9-3.5 3.1-5.4 2.3-1.9-.9-2.1-2.9-2-5.6\"></path></g><defs><path id=\"m\" d=\"M204.5 193h15.8v8.6h-15.8z\"></path></defs><clipPath id=\"n\"><use xlink:href=\"#m\" overflow=\"visible\"></use></clipPath><g opacity=\".25\" clip-path=\"url(#n)\"><path fill=\"#FCD4C3\" d=\"M204.576 195.158c13.6-6.7 16.4 4.2 15.7 6.4-5.4.9-14.9-4.7-15.7-6.4\"></path></g><defs><path id=\"o\" d=\"M223 190.9h5.7v5H223z\"></path></defs><clipPath id=\"p\"><use xlink:href=\"#o\" overflow=\"visible\"></use></clipPath><g opacity=\".5\" clip-path=\"url(#p)\"><path fill=\"#FCD4C3\" d=\"M224.351 190.896c-2.3 2.6-1.2 4.7.3 5 1.9.4 4.4-1.6 4-1.6-.5 0-4.2 1.2-4.9-.6-.5-1.4.3-2.2.6-2.8\"></path></g><defs><path id=\"q\" d=\"M66.1 182.6H195v36.5H66.1z\"></path></defs><clipPath id=\"r\"><use xlink:href=\"#q\" overflow=\"visible\"></use></clipPath><g opacity=\".15\" clip-path=\"url(#r)\"><path fill=\"#E3AB5E\" d=\"M69.034 208.266c43.7 25.1 130.4-.4 125.8-8.6-6.1-10.9-8.5-17.7-21.9-17.1-13.3.7-98.9 7.5-102.4 10.1-3.4 2.7-7.2 12.3-1.5 15.6\"></path></g><path fill=\"#FFF8EE\" d=\"M164.3 57.5c19.6-1.8 31.1-22.1 43-19-8 5-15.9 15-27 31.4-2.7 3.9-21.4-11.9-16-12.4\"></path><path fill=\"none\" stroke=\"#E5D0AE\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" d=\"M164.3 57.5c19.6-1.8 31.1-22.1 43-19-8 5-15.9 15-27 31.4-2.7 3.9-21.4-11.9-16-12.4z\"></path><path fill=\"#BA8449\" d=\"M41.8 53.1c8.8-8.2 24.7-5 37.5-.4 7.3 2.6 16.8.5 17.4 2 1.6 3.5-7.9 10.7-15.7 10.5-7.7-.1-20.6-14.6-39.2-12.1\"></path><path fill=\"none\" stroke=\"#895B2E\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" d=\"M41.8 53.1c8.8-8.2 24.7-5 37.5-.4 7.3 2.6 16.8.5 17.4 2 1.6 3.5-7.9 10.7-15.7 10.5-7.7-.1-20.6-14.6-39.2-12.1z\"></path><path fill=\"#FCD4C3\" d=\"M177.7 67.2c4.5 1.3 21.6-32.2 29.9-28.9 26.4 10.5-8 50.9-18.9 51.8-11 .8-13.5-23.7-11-22.9\"></path><path fill=\"none\" stroke=\"#F8A38F\" stroke-width=\"2\" stroke-miterlimit=\"10\" d=\"M177.7 67.2c4.5 1.3 21.6-32.2 29.9-28.9 26.4 10.5-8 50.9-18.9 51.8-11 .8-13.5-23.7-11-22.9z\"></path><path fill=\"#FCD4C3\" d=\"M82.3 63.2c-7.3 3.2-33.2-23.9-44.1-6.5C31 68.2 52.8 91.4 68.4 93.9s17.7-32.4 13.9-30.7\"></path><path fill=\"none\" stroke=\"#F8A38F\" stroke-width=\"2\" stroke-miterlimit=\"10\" d=\"M82.3 63.2c-7.3 3.2-33.2-23.9-44.1-6.5C31 68.2 52.8 91.4 68.4 93.9s17.7-32.4 13.9-30.7z\"></path><defs><path id=\"s\" d=\"M180.5 44.8h18v44.6h-18z\"></path></defs><clipPath id=\"t\"><use xlink:href=\"#s\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#t)\"><path fill=\"#FCD4C3\" d=\"M198.067 44.8c-1.4 4.6-13.2 16.5-11.6 26.7.6 3.8 4.6 15 6.3 14.6s6-3.1 5.6-2.5c-.4.6-6 4.7-8.1 5.8-2.1-1.1-11-21.8-9.7-22.9 3.9-3.5 15.8-21.5 17.5-21.7\"></path></g><defs><path id=\"u\" d=\"M38.6 51.5h44.2v31.6H38.6z\"></path></defs><clipPath id=\"v\"><use xlink:href=\"#u\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#v)\"><path fill=\"#FCD4C3\" d=\"M38.533 57.4c8-4.9 22.6-2.8 31.1 5.5 3 3 3.9 13-2.9 19.8-2.7 2.7 16-9.6 16.1-13.2 0-3.6-1.2-4.6-4-5.6-10.3-3.8-21.1-12.6-30.5-12.4-6.1.1-8.9 4.3-9.8 5.9\"></path></g><defs><path id=\"w\" d=\"M181.1 42.2h26.2v44.2h-26.2z\"></path></defs><clipPath id=\"x\"><use xlink:href=\"#w\" overflow=\"visible\"></use></clipPath><g opacity=\".25\" clip-path=\"url(#x)\"><path fill=\"#FCD4C3\" d=\"M201.3 42.175c18.2 10-11.1 25.2-8.9 44.1-3.8-.4-13.2-18.7-10.9-20.3 3.2-2.2 16.7-24.6 19.8-23.8\"></path></g><path fill=\"#E5D0AE\" d=\"M60.9 103.6c.3-1.3.5-2.7.5-4 .1-1.4.2-2.8.5-4.1.1-.7.3-1.4.6-2 .3-.6.5-1.3.7-1.9.5-1.3 1-2.6 1.6-3.8 2.3-5.1 4.9-9.9 8.1-14.4 3.2-4.5 6.7-8.7 10.7-12.3 4-3.7 8.7-6.7 13.7-8.7 5-2.1 10.4-3.4 15.8-4 5.4-.7 10.8-.8 16.2-.7 5.4.1 10.8.4 16.2 1.1 5.4.7 10.8 1.9 16 3.8 2.6 1 5.1 2.1 7.5 3.5 2.4 1.4 4.7 3.1 6.8 5.1 2.1 1.9 3.9 4.2 5.4 6.6 1.5 2.4 2.6 5 3.6 7.7.9 2.6 1.6 5.3 2.2 8s1 5.3 1.6 7.8c.3 1.2.7 2.4 1.1 3.6.5 1.2 1 2.5 1.4 3.8.9 2.5 1.9 5.1 2.8 7.6 3.5 10.2 6.6 20.6 8.5 31.2.9 5.3 1.6 10.7 1.7 16.1.1 5.4-.4 10.8-1.9 16-.4 1.3-.8 2.6-1.3 3.8-.5 1.2-1.2 2.4-1.6 3.7-.2.7-.4 1.3-.7 1.9-.3.6-.7 1.2-1.1 1.8-.7 1.1-1.6 2.3-2.5 3.3-3.5 4.2-8 7.6-12.8 10.2s-10 4.6-15.2 6.1c-5.3 1.5-10.5 2.7-15.9 3.7s-10.7 1.7-16 2.4l-8.1.9-4 .4c-1.3.1-2.7.2-4.1.3-11 .6-22-1-32.5-3.9-5.3-1.5-10.4-3.3-15.4-5.5s-9.9-4.7-14.5-7.7c-2.3-1.5-4.6-3.2-6.7-5.1-.5-.5-1.1-1-1.6-1.5s-.9-1.1-1.4-1.6c-.9-1.1-1.8-2.2-2.6-3.3-3.1-4.6-5.6-10-6.4-15.6-.9-5.7-.1-11.5 1.5-16.8 1.6-5.4 4.1-10.3 6.7-15.1 2.7-4.7 5.6-9.3 8.4-13.8 1.4-2.3 2.7-4.6 3.9-6.9 1.1-3 2.1-5.3 2.6-7.7zm4 .9c-.7 2.8-1.9 5.4-3.2 7.9s-2.7 4.8-4.1 7.1c-2.8 4.6-5.7 9.1-8.2 13.7s-4.8 9.4-6.2 14.3c-1.4 4.9-2 10-1.2 15 .8 4.9 2.9 9.6 5.9 13.7.7 1 1.6 2 2.4 3 .4.5.9 1 1.3 1.4.4.5.9.9 1.3 1.3 1.8 1.7 3.9 3.2 6.1 4.7 4.4 2.8 9 5.3 13.9 7.4 4.8 2.1 9.8 3.9 14.9 5.3s10.2 2.5 15.4 3.2c5.2.7 10.4.9 15.6.7l3.9-.3 4-.4c2.6-.2 5.3-.5 8-.8 5.3-.5 10.6-1.2 15.8-2.1 5.3-.9 10.4-1.9 15.5-3.3s10.1-3 14.9-5.1c4.7-2.2 9.3-4.9 13-8.6.9-.9 1.8-1.9 2.6-2.9.4-.5.8-1.1 1.2-1.6.4-.5.9-1 1.3-1.6.9-1.1 1.3-2.3 1.9-3.5.5-1.2.9-2.5 1.2-3.8 1.3-5.2 1.6-10.6 1.3-15.9-.4-5.3-1.3-10.6-2.6-15.8-2.5-10.4-6.2-20.4-10.1-30.3-1-2.5-2-5-3-7.4l-1.6-3.7c-.5-1.3-1-2.7-1.4-4-.7-2.7-1.2-5.3-1.8-7.9-.5-2.6-1.2-5.1-2-7.5-1.7-4.9-4.2-9.3-7.9-12.8-3.6-3.5-8.1-6.2-12.9-8.2-4.8-2-10-3.3-15.2-4.2-5.2-.9-10.5-1.4-15.8-1.7-5.3-.2-10.7-.3-16 .3-5.3.6-10.5 1.7-15.4 3.8-4.9 2-9.4 4.9-13.2 8.5-3.9 3.6-7 8-9.3 12.6-2.4 4.7-4.1 9.7-5.6 14.7-.4 1.2-.7 2.5-1 3.8-.2.6-.3 1.3-.5 1.9-.1.3-.1.7-.2 1-.1.3-.2.6-.4.9-.5 1.2-1.1 2.4-1.7 3.6-.2 1.1-.6 2.3-.9 3.6z\"></path><path fill=\"#FFF8EE\" d=\"M62.9 104.1c-4.2 18.6-40.9 48-13 78.1 9.5 10.2 40.3 25.9 71.2 23 80.4-7.6 100.7-27 66.8-110.2-5.5-13.5.7-44.7-58.4-46.5-24.8-.7-54.6 2.7-66.6 55.6\"></path><path fill=\"#E5BFA1\" d=\"M76.8 67.7c2.6-4 6-7.3 9.8-10C90.4 55 94.7 53 99 51.4c8.8-3.2 18-4.4 27.2-4.7 9.2-.2 18.5.5 27.5 2.8 4.5 1.2 8.9 2.8 13.1 5.1s8.1 5.1 11.4 8.6c3.3 3.5 6 7.4 8.1 11.7 2.1 4.3 3.6 8.8 4.7 13.3 1.1 4.6 1.8 9.1 2.4 13.6.3 2.3.6 4.5 1.1 6.6.2 1.1.5 2.1.8 2.9l.3.6.1.1.1.1.2.4.9 1.5c4.4 8.1 7.7 17 8.9 26.3.6 4.6.7 9.3.2 14-.5 4.6-1.7 9.2-3.5 13.5-.9 2.1-1.9 4.2-3.1 6.3l-.9 1.5c-.3.5-.6.9-1 1.5-.1.1-.1.2-.2.3-.3-.2.4.7-1.6 0-.5-.9-.2-.7-.3-.9 0-.3.1-.4.1-.6l.3-.9.5-1.6c1.4-4.3 2.6-8.6 3.1-13.1.2-2.2.3-4.4 0-6.7-.3-2.2-.9-4.3-2-6.1-.3-.5-.6-.9-1-1.3s-.7-.8-1.1-1.2c-.8-.8-1.6-1.5-2.5-2.2-1.8-1.4-3.7-2.5-5.7-3.5-4.1-1.8-8.6-2.5-13-2.3-4.5.2-8.9 1.1-13.2 2.3-2.2.6-4.3 1.3-6.5 2-1.1.4-2.2.7-3.3 1-.6.2-1.1.3-1.8.4-.6.1-1.1.2-1.7.2-4.6.5-9.1.8-13.8.7-4.6-.1-9.2-.6-13.8-1.6-4.5-1-9-2.5-13.2-4.4-4.2-2-8.2-4.4-11.8-7.4-3.6-3-6.8-6.4-9.6-10.1-5.6-7.5-9.3-16.2-11.1-25.3-.9-4.6-1.3-9.2-1.1-13.9.1-2.3.4-4.7.9-7 .6-1.8 1.4-4.1 2.7-6.2zm2 1.3c-1.1 1.8-1.8 3.8-2.3 6-.5 2.1-.7 4.3-.9 6.5-.2 4.4.3 8.9 1.2 13.2 1.9 8.7 5.6 17 11 24 2.7 3.5 5.8 6.7 9.2 9.5 3.4 2.8 7.2 5.2 11.2 7.1 4 1.9 8.2 3.3 12.6 4.3 4.3 1 8.8 1.6 13.2 1.7 4.5.2 8.9 0 13.4-.5l1.7-.2c.5-.1 1-.2 1.6-.3 1.1-.3 2.1-.6 3.2-.9 2.2-.6 4.4-1.3 6.6-1.8 4.4-1.1 9-1.9 13.7-1.9 4.6 0 9.3.8 13.5 2.8 2.1 1 4.1 2.2 5.9 3.6.9.7 1.8 1.5 2.6 2.3l1.2 1.2c.4.4.8.9 1.1 1.4 1.3 2 2 4.3 2.3 6.7s.3 4.7.1 7c-.4 4.6-1.4 9.1-2.7 13.5l-.5 1.6-.2.8c0 .1-.1.3 0 .3-.1-.1.2.2-.2-.7-1.9-.7-1.2.2-1.4-.1.2-.4.5-.9.8-1.4.3-.5.5-1 .8-1.5 1-2 1.9-4 2.7-6.1 3-8.3 3.6-17.4 2.1-26.1-.7-4.4-2-8.6-3.6-12.7s-3.5-8.1-5.7-12l-.8-1.4-.2-.4-.1-.2-.1-.2c-.2-.3-.3-.6-.4-.9-.5-1.2-.8-2.5-1.1-3.6-.5-2.3-.9-4.6-1.2-6.8-.7-4.5-1.3-8.9-2.4-13.2-1-4.3-2.4-8.5-4.3-12.4-1.9-3.9-4.2-7.5-7.2-10.7-5.8-6.3-13.8-10.5-22.3-13s-17.5-3.3-26.5-3.3c-8.9 0-17.9 1.1-26.3 3.9-4.2 1.4-8.2 3.3-11.9 5.8-3.8 2.4-7 5.4-9.4 9.1z\"></path><path fill=\"#895B2E\" d=\"M75.6 67.2c1.5-2.4 3.3-4.3 5.1-6.1 1.9-1.8 3.9-3.3 6-4.7 4.2-2.8 8.7-5 13.4-6.7 9.4-3.3 19.3-4.6 29.1-4.4 9.7.3 19.5 1.5 28.9 4.9 4.7 1.7 9.2 3.9 13.3 6.9 4.1 2.9 7.7 6.5 10.7 10.6 2.9 4.1 5.1 8.6 6.8 13.3 1.6 4.7 2.7 9.5 3.5 14.2.4 2.4.7 4.7 1.1 7.1.4 2.3.7 4.7 1.1 6.8.2 1.1.5 2.1.9 2.9l.1.2.1.2.2.4.4.8.9 1.6c1.1 2.1 2.2 4.3 3.2 6.5 1.9 4.4 3.5 9.1 4.6 13.9 1.1 4.7 1.6 9.6 1.6 14.5-.1 9.8-2.8 19.5-7.9 27.8-.4.6-1.2.9-1.8.5-.6-.4-.8-1.1-.6-1.6 1.4-3.6 2.9-7 4-10.5 1.2-3.5 2-7.1 2-10.6s-.9-6.9-3-9.6c-.1-.2-.3-.4-.4-.5l-.2-.2-.2-.3-.9-.9c-.6-.6-1.3-1.2-2-1.7-1.4-1.1-3-2.1-4.5-3.1-6.3-3.9-13-7.3-19.8-10.7-6.8-3.3-13.7-6.5-20.5-9.6-13.8-6.3-27.6-12.6-41.2-19.4-6.8-3.5-13.5-7-20.1-11.2-3.5-2.5-6.7-4.7-9.8-7.5-1.5-1.4-3-3-4.2-5.2-.6-1.1-1.1-2.4-1.2-4 0-.8 0-1.6.2-2.4.1-.4.2-.8.4-1.2.1-.3.4-.9.5-1h.2zm5.6 3.4c-.2.3-.1.2-.2.3 0 .1 0 .1-.1.2v.4c0 .3.2.8.4 1.4.6 1.2 1.7 2.5 2.9 3.6 2.5 2.4 5.4 4.6 8.5 6.6 6.1 4.1 12.7 7.7 19.4 11.3 13.3 7 27 13.5 40.6 20.1 6.8 3.3 13.6 6.7 20.4 10.1 6.8 3.5 13.5 7 20 11.3 1.6 1.1 3.2 2.2 4.7 3.5.8.6 1.5 1.3 2.3 2 .4.4.7.7 1.1 1.2l.2.3.3.3c.2.2.3.4.5.6 1.2 1.7 2.1 3.6 2.7 5.6s.7 4.1.7 6.1c-.1 4-1.2 7.9-2.5 11.6-1.3 3.7-2.9 7.1-4.4 10.6l-2.4-1.2c4.7-8 6.9-17.2 6.8-26.4-.2-9.2-2.6-18.3-6.5-26.7-1-2.1-2-4.2-3.2-6.2l-1.8-3.2c-.7-1.3-1-2.6-1.3-3.8-.6-2.5-1-4.8-1.4-7.2s-.8-4.7-1.2-6.9c-.9-4.6-2-9-3.6-13.3-1.6-4.2-3.7-8.3-6.3-11.8-2.6-3.6-5.9-6.7-9.5-9.2-3.7-2.5-7.7-4.5-12-5.9-8.6-2.9-17.8-3.9-27-4-4.6 0-9.1.2-13.6 1-4.5.7-8.9 1.8-13.1 3.3s-8.3 3.4-12 5.8c-1.9 1.2-3.6 2.5-5.2 4s-3.1 3-4.2 4.6z\"></path><path fill=\"#BA8449\" d=\"M77.8 68.3c-11 17 2.1 82.3 71.2 73.5 7.3-.9 31.6-13.9 48 4.3 8.9 10-3.1 35.3 0 30 3.5-5.8 16.9-28.2-3.2-62.7-6.4-11.1 4.2-64.4-65-65.1-26.5-.1-43.7 8.7-51 20\"></path><defs><path id=\"y\" d=\"M61.7 64.6H179v111.9H61.7z\"></path></defs><clipPath id=\"z\"><use xlink:href=\"#y\" overflow=\"visible\"></use></clipPath><g opacity=\".15\" clip-path=\"url(#z)\"><path fill=\"#E3AB5E\" d=\"M75.968 72.433c19.9-12.8 80.1-11.9 99.3 18.8 12.8 20.4-10.6 70.8-19.3 77.2-8.6 6.4-20.6 12-52.2 4.4-26.8-6.4 13.5-31.3-17.9-34.9-28.7-3.3-31.6-51.5-9.9-65.5\"></path></g><defs><path id=\"A\" d=\"M118.5 119.2h13.1v5.5h-13.1z\"></path></defs><clipPath id=\"B\"><use xlink:href=\"#A\" overflow=\"visible\"></use></clipPath><g opacity=\".25\" clip-path=\"url(#B)\"><path fill=\"#E3AB5E\" d=\"M131.6 121.966c0 1.5-2.9 2.8-6.5 2.8s-6.5-1.2-6.5-2.8c0-1.5 2.9-2.8 6.5-2.8 3.6.1 6.5 1.3 6.5 2.8\"></path></g><path fill=\"#F8A38F\" d=\"M120.1 113.8c1.5-1 9.5-.7 10.5.4 1 1 3.2 5.2.7 7-.9.6-.9-1.9-2.9-1.5-2.4.5-1.1 3.6-3 3.6-2.9-.1-.1-3.4-2.6-3.8-1.9-.4-2.3 1.5-3.2 1.3-2.9-.6-1.6-5.6.5-7\"></path><defs><path id=\"C\" d=\"M117.9 113.2h14.5v9.9h-14.5z\"></path></defs><clipPath id=\"D\"><use xlink:href=\"#C\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#D)\"><path fill=\"#F8A38F\" d=\"M124.42 113.205c-1.9 0-3.7.2-4.3.6-2.1 1.4-3.4 6.4-.6 6.9h.1c.7 0 1.1-1.4 2.6-1.4h.5c2.5.4-.2 3.8 2.6 3.8 1.8 0 .5-3 3-3.5h.4c1.4 0 1.6 1.6 2.2 1.6.1 0 .2 0 .3-.1 2.6-1.8.4-6-.7-7-.5-.5-3.4-.9-6.1-.9m0 .7c3 0 5.3.4 5.7.7.6.6 1.8 2.8 1.6 4.4-.1.6-.3 1.1-.7 1.4 0-.1-.1-.1-.2-.2-.4-.5-1-1.3-2.1-1.3-.2 0-.4 0-.5.1-1.7.4-2 1.7-2.3 2.6-.2.9-.3.9-.6.9-.8 0-.8-.2-.8-1.1 0-.9 0-2.3-1.8-2.6h-.6c-1.1 0-1.8.7-2.3 1.1-.1.1-.3.3-.4.3-.4-.1-.8-.3-1-1.1-.3-1.4.7-3.8 1.8-4.6.6-.4 2-.6 4.2-.6\"></path></g><defs><path id=\"E\" d=\"M74.1 124.9H187V189H74.1z\"></path></defs><clipPath id=\"F\"><use xlink:href=\"#E\" overflow=\"visible\"></use></clipPath><g opacity=\".25\" clip-path=\"url(#F)\"><path fill=\"#F7E8D0\" d=\"M186.799 140.05c3 19.2-21 43.3-53.3 48.3-32.3 4.9-56.1-23.9-59.1-43.2-3-19.2 16.8-11.9 49.1-16.8s60.3-7.5 63.3 11.7\"></path></g><defs><path id=\"G\" d=\"M80 125.9h93.6v47.5H80z\"></path></defs><clipPath id=\"H\"><use xlink:href=\"#G\" overflow=\"visible\"></use></clipPath><g opacity=\".5\" clip-path=\"url(#H)\"><path fill=\"#D8CAB2\" d=\"M102.515 169.277c-.9-1.4-1.4-3.1-1.9-4.7l-1.5-4.8c-1-3.2-2.1-6.4-3.6-9.4s-3.4-5.8-5.8-7.9c-2.4-2.1-5.3-3.5-8.4-4.1-1.1-.4-1.6-1.5-1.2-2.5.4-1 1.4-1.5 2.3-1.3 7.2 1.7 14.7 2.5 22.1 2.6s15-.3 22.5-1.2c7.5-.9 14.9-2.2 22.2-3.9 7.3-1.7 14.6-3.7 21.7-6.1 1.1-.4 2.2.2 2.5 1.2.3.8 0 1.6-.6 2.1-.2.2-.6.5-.9.8-.3.3-.6.7-.9 1-.6.7-1.2 1.5-1.8 2.3-1.2 1.6-2.3 3.2-3.3 4.9-2.2 3.3-4.2 6.7-6.1 10.2-1.9 3.5-3.8 7-5.5 10.5-.9 1.8-1.7 3.6-2.4 5.4-.4.9-.7 1.8-1.1 2.8-.2.5-.3.9-.4 1.4v.2c0 .1 0 .1-.1.2 0 .1-.1.2-.2.2-.1.1-.2.2-.4.3-.2.2-.5.3-.7.4-1.9.8-3.9 1.2-5.8 1.6-1.9.4-3.9.7-5.9.9-4 .5-7.9.9-11.9 1-4 .2-8 .2-11.9-.2-2-.2-4-.5-5.9-1-1-.3-1.9-.6-2.8-1.1-.9-.4-1.7-1-2.3-1.8m.1-.1c.5.8 1.4 1.4 2.3 1.8.9.4 1.8.7 2.8 1 1.9.5 3.9.8 5.9.9 4 .3 7.9.3 11.9.1 4-.2 7.9-.7 11.8-1.2 1.9-.3 3.9-.6 5.8-1.1s3.9-.9 5.6-1.7c.2-.1.4-.2.6-.4.2-.1.3-.2.3-.3.1-.5.2-1 .4-1.5.3-1 .6-1.9.9-2.9.7-1.9 1.4-3.7 2.2-5.6 1.6-3.7 3.2-7.3 4.9-10.9 1.7-3.6 3.5-7.2 5.4-10.7.9-1.8 1.9-3.5 3-5.3.5-.9 1.1-1.8 1.7-2.6.3-.4.6-.9.9-1.3.4-.4.7-.9 1.2-1.3l1.9 3.4c-7.3 2.5-14.6 4.5-22.1 6.2-7.5 1.7-15 3.1-22.6 4-7.6.9-15.3 1.4-23 1.2s-15.4-1.1-23-2.9l1.1-4c3.3 2 6.3 3.9 8.6 6.6 2.3 2.7 3.9 5.8 5.2 9 1.2 3.2 2.2 6.5 3 9.7.4 1.6.9 3.3 1.3 4.9.6 1.9 1.1 3.5 2 4.9\"></path></g><defs><path id=\"I\" d=\"M81 126.9h91.6v46.5H81z\"></path></defs><clipPath id=\"J\"><use xlink:href=\"#I\" overflow=\"visible\"></use></clipPath><g opacity=\".5\" clip-path=\"url(#J)\"><path fill=\"#D8CAB2\" d=\"M102.532 169.288c-.9-1.4-1.4-3-1.9-4.6-.5-1.6-.9-3.2-1.4-4.8-1-3.2-2-6.4-3.5-9.5-1.4-3-3.3-5.8-5.6-8-2.4-2.3-5.3-3.9-8.4-4.6v-.1c-.5-.2-.8-.8-.6-1.3.2-.5.7-.8 1.2-.7 7.3 1.7 14.8 2.5 22.4 2.6s15.1-.3 22.6-1.2c7.5-.9 14.9-2.3 22.3-3.9 7.4-1.7 14.7-3.7 21.8-6.1.5-.2 1.1.1 1.3.6.1.4 0 .8-.3 1.1-.6.5-1.3 1.3-1.9 2-.6.7-1.2 1.6-1.8 2.3-1.1 1.6-2.2 3.3-3.2 5-2.1 3.3-4.1 6.8-6 10.3-1.9 3.5-3.7 7-5.3 10.6l-2.4 5.4c-.4.9-.7 1.8-1 2.8-.2.5-.3.9-.4 1.4-.1.4-.4.5-.6.7-.2.2-.5.3-.7.4-1.9.8-3.9 1.2-5.8 1.6-1.9.4-3.9.7-5.9 1-3.9.5-7.9.9-11.9 1.1-4 .2-8 .2-11.9-.2-2-.2-4-.5-5.9-1-1-.3-1.9-.6-2.8-1-1-.5-1.9-1.1-2.4-1.9m0-.1c.5.8 1.4 1.4 2.3 1.9.9.4 1.8.7 2.8 1 1.9.5 3.9.8 5.9.9 4 .4 7.9.3 11.9.1 4-.2 7.9-.6 11.9-1.2 1.9-.3 3.9-.6 5.9-1.1 1.9-.4 3.9-.9 5.6-1.7.2-.1.4-.2.6-.4.2-.1.4-.3.4-.4.1-.5.2-1 .4-1.5.3-1 .6-1.9 1-2.8.7-1.9 1.5-3.7 2.3-5.5 1.6-3.7 3.3-7.2 5.1-10.8 1.8-3.6 3.6-7.1 5.6-10.6 1-1.8 2-3.5 3.1-5.1.5-.9 1.1-1.7 1.7-2.5.6-.8 1.2-1.6 2.1-2.4l1 1.8c-7.2 2.5-14.6 4.5-22 6.2s-14.9 3-22.5 4c-7.6.9-15.2 1.4-22.9 1.2-7.6-.2-15.3-1-22.8-2.7l.5-1.9c3.3 1.3 6.3 3.3 8.6 5.9 2.3 2.6 4 5.6 5.3 8.7 1.3 3.1 2.3 6.3 3.2 9.6.4 1.6.9 3.2 1.4 4.9.2 1.4.7 3 1.6 4.4\"></path></g><path fill=\"#333\" d=\"M102.6 169.2c5.1 8 46.8 2.5 47.5-.7 1.8-8.1 16.8-36.7 21.6-40.7-8.6 3-53.3 17.3-89.6 8.6 16.3 5.5 16.5 26.6 20.5 32.8\"></path><g><defs><path id=\"K\" d=\"M82 127.9h89.6v45.4H82z\"></path></defs><clipPath id=\"L\"><use xlink:href=\"#K\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#L)\"><path fill=\"#333\" d=\"M171.55 127.95c-6.7 2.3-34.9 11.4-64.1 11.4-8.6 0-17.2-.8-25.5-2.7 16.4 5.3 16.6 26.5 20.6 32.7 1.9 3 9.2 4.1 17.5 4.1 13.4 0 29.5-2.8 30-4.8 1.8-8.2 16.7-36.8 21.5-40.7m-5.6 3.9c-6.5 9.8-15.9 28.7-17.8 35.8-2.5 1.4-15.4 3.8-28.1 3.8-10.2 0-14.8-1.7-15.8-3.2-1-1.5-1.8-4.3-2.6-7.5-1.7-6.1-4.1-14.5-9.8-20.3 5 .6 10.2.9 15.7.9 23.8-.1 47.1-6.1 58.4-9.5\"></path></g></g><path fill=\"#FCD4C3\" d=\"M119.7 173.4c-8.6 0-14.2-1.2-16.4-3.6-.2-.2-.2-1.4.8-3.7 2.4-5.5 9.8-14.9 22.6-15.7.9 0 1.7-.1 2.5-.1 15 0 24 7.6 24 8.9-.2.4-.4 1-.7 1.8-.8 1.9-2 4.9-3.1 8.1-1.3 1.3-16.3 4.3-29.7 4.3\"></path><path fill=\"#F8A38F\" d=\"M129.2 149.8c-.9 0-1.7 0-2.6.1-17.5 1.1-25.6 18.4-23.8 20.5 2.6 2.8 9.3 3.8 16.9 3.8 13.5 0 29.8-3.1 30.3-4.6 1.5-4.5 3.2-8.2 3.9-10 .6-1.8-9.5-9.9-24.7-9.8m0 1.3c13.4 0 22.4 6.4 23.3 8.3-.2.4-.4.9-.6 1.5-.8 1.9-2 4.7-3.1 7.9-2.1 1.2-16.1 3.9-29.1 3.9-8.1 0-13.7-1.2-15.8-3.3-.1-.7.6-3.5 3.1-7 2.2-3.2 8.6-10.7 19.7-11.3h2.5\"></path><g><defs><path id=\"M\" d=\"M103.1 149.4h50.2v20.7h-50.2z\"></path></defs><clipPath id=\"N\"><use xlink:href=\"#M\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#N)\"><path fill=\"#FCD4C3\" d=\"M103.084 169.317c-1.2 5.4 31.9-21.1 49.7-8.4 3.7-4.9-16-13.2-27.5-11.3-9.7 1.7-19.7 7.9-22.2 19.7\"></path></g></g><path fill=\"#FFF7E3\" d=\"M109.8 140.8c1.7 3 4.8 17.6 6.1 17.9s9.5 2.6 10.6 2.1c1.2-.5 1.1-3.3 2.3-2.5 1 .7 1.5 2 2.5 1.5 1.8-.9 7.1-4.2 8-5.6.8-1.5.7-9.8 0-16.4-3.4 1.6-23.5 3.7-29.5 3\"></path><g><defs><path id=\"O\" d=\"M109.8 137.9h30.1v23.2h-30.1z\"></path></defs><clipPath id=\"P\"><use xlink:href=\"#O\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#P)\"><path fill=\"#FFDC99\" d=\"M139.35 137.85c-3 1.3-18.7 3.1-26.6 3.1-1.2 0-2.1 0-2.9-.1 1.7 3 4.8 17.6 6.1 17.9 1.2.3 8 2.2 10.1 2.2.2 0 .4 0 .5-.1 1-.4 1.1-2.6 1.9-2.6.1 0 .3 0 .4.2.9.5 1.3 1.6 2.1 1.6.1 0 .3 0 .4-.1 1.8-.9 7.1-4.2 8-5.6.9-1.5.7-9.8 0-16.5m-.5.9c.6 6.8.6 14 0 15.2-.7 1.2-5.5 4.3-7.7 5.4h-.1c-.2 0-.5-.3-.7-.6-.3-.3-.6-.6-1-.9-.3-.2-.5-.3-.8-.3-.9 0-1.2.9-1.5 1.6-.2.4-.4 1-.7 1.1h-.3c-1.7 0-6.8-1.4-8.9-1.9-.4-.1-.7-.2-.9-.2-.6-.7-1.9-5.4-2.9-8.8-.9-3.1-1.7-6-2.4-7.7h1.9c7.5 0 21.5-1.6 26-2.9\"></path></g></g><g><defs><path id=\"Q\" d=\"M109.9 137.5h29.7v10.3h-29.7z\"></path></defs><clipPath id=\"R\"><use xlink:href=\"#Q\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#R)\"><path fill=\"#EADCBE\" d=\"M112.151 147.85c-.5-5.4 24.4-7.2 27.5-6.7 0-1.3-.2-2.1-.2-3.6-4.1 2.1-26.5 4.3-29.5 3.4.3.6 1.4 3.6 2.2 6.9\"></path></g></g><g><defs><path id=\"S\" d=\"M124 143.8h5.5v14.7H124z\"></path></defs><clipPath id=\"T\"><use xlink:href=\"#S\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#T)\"><path fill=\"#FFDC99\" d=\"M124.558 143.768c.5 1.2 1 2.3 1.4 3.5l1.2 3.6 1.1 3.6 1.1 3.6-1.7.5-.8-3.7-.9-3.7-.9-3.6c-.4-1.2-.7-2.4-1.1-3.5l.6-.3z\"></path></g></g><g><defs><path id=\"U\" d=\"M39.1 51.5h39.4v35.7H39.1z\"></path></defs><clipPath id=\"V\"><use xlink:href=\"#U\" overflow=\"visible\"></use></clipPath><g opacity=\".4\" clip-path=\"url(#V)\"><path fill=\"#FCD4C3\" d=\"M40.384 59.116c13.2 3.4 11.1 26.2 18.9 28 7.9 1.8 18.2-18.8 19.2-23.3-15.2-6.5-22.3-14.1-33.2-11.9-3.6.7-8.6 6.2-4.9 7.2\"></path></g></g><g><defs><path id=\"W\" d=\"M59.9 88.7h133.7v42.5H59.9z\"></path></defs><clipPath id=\"X\"><use xlink:href=\"#W\" overflow=\"visible\"></use></clipPath><g opacity=\".5\" clip-path=\"url(#X)\"><path fill=\"#E3AB5E\" d=\"M76.967 125.833c16.6 1.3 30.3 2 35.2-3.1s6.7-27.7 14.7-27.1c6.8.5 9.1 29.9 13.5 30.7 4.4.9 35.5 9.4 43.3 1.4 7.7-8 11.3-13 9.5-17.8-1.8-4.8-47.3-20.3-56.6-21.2-9.3-.9-72.1 7-73.7 10.9-1.6 4-3.3 3.4-3 7.6.6 8.1.5 17.3 17.1 18.6\"></path></g></g><path fill=\"#333\" d=\"M123.5 92.4c1.2 0 5.9-.4 7 .5 6 4.7 5.8 24 12.1 30 5.6 5.4 36.2 9.3 41.5 3.2 5.3-6.1 13.1-24.7 14.9-26.1 1.8-1.3 5.8-2.3 7-4.2 1.2-1.8.2-10-2.6-9.6-2.8.4-8.1 2.1-11.4 1.2-3.3-1-19.4-11.1-59.9-5-3.9.6-7.8 0-10.5-.7S103.7 72.2 63 78c-4 .6-9.6-1.2-11.6-1-2 .2-2.6 6.5-1.8 8.1s5 3 5.5 5 4.2 21.6 13.8 29.7c10.2 8.6 36.2 2.6 38.5 1 10.3-7.3 12.6-28.4 16.1-28.4\"></path><g><defs><path id=\"Y\" d=\"M49.1 76.1h157.3v53.1H49.1z\"></path></defs><clipPath id=\"Z\"><use xlink:href=\"#Y\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#Z)\"><path fill=\"#1A1A1A\" d=\"M88.438 76.123c-7.1 0-15.6.5-25.6 2-.6.1-1.2.1-1.8.1-3.5 0-7.6-1.1-9.5-1.1h-.3c-2 .2-2.6 6.5-1.8 8.1.8 1.7 5 3 5.5 5s4.2 21.6 13.8 29.7c4 3.4 10.6 4.5 17.2 4.5 10 0 19.9-2.5 21.3-3.5 10.4-7.4 12.8-28.5 16.3-28.5.5 0 1.8-.1 3-.1 1.6 0 3.3.1 3.9.5 6 4.7 5.8 24 12.1 30 3.6 3.4 17.4 6.3 28.2 6.3 6.1 0 11.3-.9 13.2-3.1 5.3-6.1 13.1-24.7 14.9-26.1 1.8-1.4 5.8-2.3 7-4.2 1.1-1.8.2-9.6-2.5-9.6h-.2c-2.2.3-6 1.4-9.1 1.4-.8 0-1.6-.1-2.3-.3-2.6-.8-12.7-6.9-35.7-6.9-6.9 0-14.9.5-24.2 1.9-1.1.2-2.3.2-3.3.2-2.7 0-5.2-.4-7.1-.9-2-.2-11.2-5.4-33-5.4m0 2c18.1 0 27.4 3.6 30.8 5 .7.3 1.2.5 1.7.6 1.8.4 4.5 1 7.6 1 1.2 0 2.5-.1 3.6-.3 8.5-1.3 16.5-1.9 23.9-1.9 19 0 28.9 4.2 33.2 6.1.9.4 1.5.6 2 .8.9.3 1.8.4 2.9.4 2.2 0 4.6-.5 6.6-.9.9-.2 1.8-.4 2.5-.5.9 1 1.5 5.4 1 6.6-.4.6-2.1 1.4-3.3 1.9-1.2.5-2.3 1-3.1 1.6-1.1.8-2.2 2.9-5.4 9.3-3.1 6.1-6.9 13.7-9.8 17-1 1.2-4.6 2.4-11.8 2.4-10.5 0-23.9-2.8-26.9-5.7-2.8-2.6-4.2-8.7-5.6-14.6-1.6-6.6-3.1-12.8-6.6-15.6-.9-.7-2.3-1-5.1-1h-3.1c-2.8 0-4 3.3-6.1 9.3-2.3 6.6-5.6 15.5-11.3 19.6-1.3.8-10.7 3.2-20.2 3.2-7.3 0-12.8-1.4-15.9-4-3.8-3.2-9.1-10.7-12.9-27.8-.1-.4-.2-.7-.2-.9-.5-1.9-2.3-3-3.8-4-.6-.4-1.6-1.1-1.8-1.4-.4-.9 0-4.2.6-5.3.7 0 1.7.2 2.8.4 1.9.3 4.3.7 6.5.7.7 0 1.5 0 2.1-.2 8.9-1.1 17.4-1.8 25.1-1.8\"></path></g></g><g><defs><path id=\"aa\" d=\"M64.4 83.4h50.5v34.2H64.4z\"></path></defs><clipPath id=\"ab\"><use xlink:href=\"#aa\" overflow=\"visible\"></use></clipPath><g opacity=\".5\" clip-path=\"url(#ab)\"><path fill=\"none\" stroke=\"#333\" stroke-width=\"4\" stroke-miterlimit=\"10\" d=\"M66.2 90.45c-.9 1.2-1.5 18.9 6 23.7 4.9 3.2 25.7 2.5 29.9.2 6.5-3.7 12.9-20.5 11.1-22.9-3-4-24.6-9.3-40.8-5.1-2 .4-5.1 2.6-6.2 4.1z\"></path></g></g><path fill=\"#FFF\" d=\"M66.2 90.4c-.9 1.2-1.5 18.9 6 23.7 4.9 3.2 25.7 2.5 29.9.2 6.5-3.7 12.9-20.5 11.1-22.9-3-4-24.6-9.3-40.8-5.1-2 .5-5.1 2.6-6.2 4.1\"></path><g><defs><path id=\"ac\" d=\"M139.8 88.1h50.1v35h-50.1z\"></path></defs><clipPath id=\"ad\"><use xlink:href=\"#ac\" overflow=\"visible\"></use></clipPath><g opacity=\".5\" clip-path=\"url(#ad)\"><path fill=\"none\" stroke=\"#333\" stroke-width=\"4\" stroke-miterlimit=\"10\" d=\"M188.394 98.163c.8 1.3-1 18.9-9 22.8-5.3 2.5-25.8-.9-29.6-3.7-6-4.5-10.2-22-8.1-24.2 3.5-3.6 25.6-6 41.1.2 1.9.7 4.7 3.3 5.6 4.9z\"></path></g></g><path fill=\"#FFF\" d=\"M188.4 98.2c.8 1.3-1 18.9-9 22.8-5.3 2.5-25.8-.9-29.6-3.7-6-4.5-10.2-22-8.1-24.2 3.5-3.6 25.6-6 41.1.2 1.9.7 4.6 3.2 5.6 4.9\"></path><path d=\"M89.9 101.2c-.5 3.9-2.5 6.8-4.4 6.5-1.9-.3-2.9-3.6-2.4-7.5s2.5-6.8 4.4-6.5c1.9.3 2.9 3.6 2.4 7.5M169.6 105.6c.4 3.9-.8 7.2-2.6 7.4-1.9.2-3.7-2.8-4.1-6.7-.4-3.9.8-7.2 2.6-7.4 1.8-.1 3.6 2.9 4.1 6.7\"></path><g><defs><path id=\"ae\" d=\"M49.1 81.6h156.3v46H49.1z\"></path></defs><clipPath id=\"af\"><use xlink:href=\"#ae\" overflow=\"visible\"></use></clipPath><g opacity=\".3\" clip-path=\"url(#af)\"><path fill=\"#333\" d=\"M51.475 82.75c2.3 1.5 4.4.6 4.9 3.6s7.4 29 16 32c14.1 4.9 31.9.1 34.3-1.4 2.4-1.5 13.7-26.8 15.6-27.8 1.9-1 7.9.1 9.2.7 3.9 1.7 11.1 29.1 13 30.5 8.7 6.1 36.6 5.6 37.9 4 1.4-1.7 11.8-25.6 13.7-27 2.7-2.1 9-3.5 9.2-2.6.2.9-5.1 1.8-6.7 3.7-1.6 2-12.1 24.9-15.4 26.9-3.3 2-27.7 5.3-40.1-3.4-5.9-4.2-8.2-29.1-12.9-30.5-3-.9-5.3-.8-7.5-.2-2.9 1.9-7 23.1-15.7 28.4-3.5 2.1-30.6 7.4-38.7-1.1-15.1-15.8-10.5-29.9-15.4-31.9-3.3-1.4-4-3.2-4-4.4.3-1.3 1.4-.3 2.6.5\"></path></g></g><g><defs><path id=\"ag\" d=\"M51.6 77.2h20.2v3H51.6z\"></path></defs><clipPath id=\"ah\"><use xlink:href=\"#ag\" overflow=\"visible\"></use></clipPath><g opacity=\".3\" clip-path=\"url(#ah)\"><path fill=\"#333\" d=\"M51.75 77.45c-1.6-.6 6.8 2.9 9.9 2.7 3.1-.2 8.3-2.4 10-2.9 1.5-.5-7.8 1.2-10.1 1.1s-8.9-.6-9.8-.9\"></path></g></g><g><defs><path id=\"ai\" d=\"M116.6 82.1h21.7v5.3h-21.7z\"></path></defs><clipPath id=\"aj\"><use xlink:href=\"#ai\" overflow=\"visible\"></use></clipPath><g opacity=\".3\" clip-path=\"url(#aj)\"><path fill=\"#333\" d=\"M116.6 82.15c2.9 1.3 4.2 4.6 7 4.9s6.2.8 7.8-.1c1.6-.9 5.6-3 6.7-3.2 1.2-.2-8.7 1.3-12.4 1-3.7-.4-8-2.5-9.1-2.6\"></path></g></g><g><defs><path id=\"ak\" d=\"M187.4 86h12.3v3.9h-12.3z\"></path></defs><clipPath id=\"al\"><use xlink:href=\"#ak\" overflow=\"visible\"></use></clipPath><g opacity=\".3\" clip-path=\"url(#al)\"><path fill=\"#333\" d=\"M187.575 85.975c-1.2-.5 4.4 4 6.1 3.8 1.7-.2 4.7-2.1 6-2.6 1-.4-4 1-5.5.7-1.5-.1-5.4-1.4-6.6-1.9\"></path></g></g><g><defs><path id=\"am\" d=\"M62.3 82.8h28.9v28.6H62.3z\"></path></defs><clipPath id=\"an\"><use xlink:href=\"#am\" overflow=\"visible\"></use></clipPath><g opacity=\".3\" clip-path=\"url(#an)\"><path fill=\"#333\" d=\"M63.05 87.825c7.4-7.3 25-4.8 28.2-4.2-21.1 1.5-21.5 3.1-25.2 6.8-.5 2.9-1.2 12.5 2.1 20.9-3.7-2-7.6-21-5.1-23.5\"></path></g></g><g><defs><path id=\"ao\" d=\"M165.1 87.8h27.8v30.5h-27.8z\"></path></defs><clipPath id=\"ap\"><use xlink:href=\"#ao\" overflow=\"visible\"></use></clipPath><g opacity=\".3\" clip-path=\"url(#ap)\"><path fill=\"#333\" d=\"M192.46 95.698c-6.4-8.2-24.1-8.1-27.4-7.8 20.7 4.3 20.9 5.9 24.1 10.1.2 2.9-.4 12.5-4.7 20.4 3.8-1.6 10.1-20 8-22.7\"></path></g></g><g><defs><path id=\"aq\" d=\"M65.8 84.8h47.8v27.5H65.8z\"></path></defs><clipPath id=\"ar\"><use xlink:href=\"#aq\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#ar)\"><path fill=\"#D0DDDC\" d=\"M66.412 102.575c.7-8.6 1.5-15.6 18.6-16.1 13.7-.4 24.6 2.8 26.1 6.1 1 2.1.2 11.3-6.6 19.7 4.4-3.9 11.4-19.4 8.4-21.3-11.1-7.1-33.2-7.3-41.4-4.4-1.5.5-3.9 2.2-5.5 4-.3 2.2-.3 10.8.4 12\"></path></g></g><g><defs><path id=\"as\" d=\"M66.8 103H102v13.9H66.8z\"></path></defs><clipPath id=\"at\"><use xlink:href=\"#as\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#at)\"><path fill=\"#D0DDDC\" d=\"M66.884 103.2c2.6 16.8 33.3 11.7 35.1 11-.1.9-16.1 5.4-29.5.2-5.4-2-5.8-13.1-5.6-11.2\"></path></g></g><g><defs><path id=\"au\" d=\"M141.2 89.5h47.7V115h-47.7z\"></path></defs><clipPath id=\"av\"><use xlink:href=\"#au\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#av)\"><path fill=\"#D0DDDC\" d=\"M186.957 110.087c.4-8.7.4-15.6-16.4-18.2-13.5-2.1-24.7-.3-26.7 2.8-1.2 1.9-1.6 11.2 4.2 20.4-3.9-4.5-9-20.6-5.7-22.2 11.9-5.7 33.9-3.2 41.6.7 1.4.7 3.7 2.6 5 4.7-.1 2.1-1.1 10.7-2 11.8\"></path></g></g><g><defs><path id=\"aw\" d=\"M150.2 110.4h36.3v11.7h-36.3z\"></path></defs><clipPath id=\"ax\"><use xlink:href=\"#aw\" overflow=\"visible\"></use></clipPath><g clip-path=\"url(#ax)\"><path fill=\"#D0DDDC\" d=\"M186.383 110.613c-4.6 16.3-34.5 7.5-36.2 6.6 0 .9 15.3 7.3 29.3 3.9 5.6-1.4 7.5-12.4 6.9-10.5\"></path></g></g><g><defs><path id=\"ay\" d=\"M87.3 95.2h2v2h-2z\"></path></defs><clipPath id=\"az\"><use xlink:href=\"#ay\" overflow=\"visible\"></use></clipPath><g opacity=\".25\" clip-path=\"url(#az)\"><path fill=\"#FFF\" d=\"M89.375 96.2c0-.5-.4-1-1-1s-1 .4-1 1 .4 1 1 1 1-.4 1-1\"></path></g></g><g><defs><path id=\"aA\" d=\"M166.3 99.9h2v2h-2z\"></path></defs><clipPath id=\"aB\"><use xlink:href=\"#aA\" overflow=\"visible\"></use></clipPath><g opacity=\".25\" clip-path=\"url(#aB)\"><path fill=\"#FFF\" d=\"M168.375 100.9c0-.5-.4-1-1-1-.5 0-1 .4-1 1s.4 1 1 1c.5 0 1-.5 1-1\"></path></g></g><g><defs><path id=\"aC\" d=\"M52 79.1h64.8v9.5H52z\"></path></defs><clipPath id=\"aD\"><use xlink:href=\"#aC\" overflow=\"visible\"></use></clipPath><g opacity=\".1\" clip-path=\"url(#aD)\"><path fill=\"#D0DDDC\" d=\"M52.025 81.675c2.4 2.7 3.9 3 7.1 2.6 31.1-4 48.3-3.9 56.8 4 1.8 1.7.8-5.1-2.6-6-26.2-6.9-45.2-.7-49.2-.2-4.1.6-7-.3-12.1-.4\"></path></g></g><g><defs><path id=\"aE\" d=\"M137.7 82.3h47.9v9.2h-47.9z\"></path></defs><clipPath id=\"aF\"><use xlink:href=\"#aE\" overflow=\"visible\"></use></clipPath><g opacity=\".1\" clip-path=\"url(#aF)\"><path fill=\"#D0DDDC\" d=\"M138.025 85.675c-.7.7-.4 7.9 3 5.2 9.8-7.8 30.3-6 44.6-1.2-2.3-4.5-19-7.6-28.4-7.5-4.5.2-17.3 1.5-19.2 3.5\"></path></g></g><path fill=\"#D0DDDC\" d=\"M197.2 91.4c0 .3-1.6.5-3.5.5s-3.5-.2-3.5-.5 1.6-.5 3.5-.5c2 0 3.5.3 3.5.5M62.4 82.8c0 .3-1.6.3-3.5 0s-3.4-.8-3.3-1.1 1.6-.3 3.5 0c1.9.2 3.4.7 3.3 1.1\"></path><g><path fill=\"#FFF\" d=\"M256.04 243.036c-.6-6.1-5.1-8.8-9.2-8.8-1.9 0-3.4.5-4 .8l-.8.4-.7.5c-1 .7-2.7 1.8-4.2 2.3-.1-1.2 0-2.8.2-4.2v-.2c1.1-10.7-1.1-17-6.7-18.6-.9-.3-1.9-.4-2.9-.4-3.4 0-6.4 1.6-8.3 3-1.6-2.1-4.4-3.2-7.8-3.2-5.1 0-9.2 2.4-10.7 6.2-.2.4-.4 1-.6 1.8-3-6.6-9.1-9.1-14.8-9.1-5.4 0-10.6 2.1-12.5 3.6-.1.1-.2.1-.3.2-5.1 3.6-9.1 8.2-11.9 13.7-1.4-4.7-4.4-9.2-9.7-12.5l-.1-.1c-.2-.1-.3-.2-.4-.2 5.3-9.3 9.9-21.7 7.1-33.5-3-12.6-10.4-14.4-14.5-14.4-1.7 0-3.5.3-5.3.9h-.2c-7.8 3.1-11.2 7.7-12 8.8-.8 1.2-9.3 14.2-11.4 33.2-.2 2.1-.5 4.3-.7 6.5-1.2-1.7-3.2-3.3-6.3-4.2-1-.3-2-.4-3-.4-4.3 0-7.8 2.6-9.7 4.4-1.6-2.4-4.2-3.9-7.1-4h-.7c-4.6 0-8.2 2-10.9 4.3-1.7-3-4.9-4.9-8.6-4.9h-1.5c-5.1 0-9.1 2.4-10.7 6.4-.1.3-.3.7-.4 1.2-4-5-9.1-7.3-16-7.3h-.7c-4.3.1-14.9 1.9-21.5 16.6-1 2.3-1.8 4.6-2.4 6.8-1.4-.7-2.8-.8-3.7-.8-3.4 0-6 1.9-7.2 3.8-1 1.5-4.2 6.7-2.6 11.9.9 2.8 2.8 4.9 5.6 6 2.5 1 5.6 1.9 7.9 2.6 1.4 3.3 4 7 8.6 10.5 3.2 2.5 7.4 3.7 12.2 3.7 8.2 0 16.1-3.5 16.9-3.9l.3-.2.1-.1c1.6 1.6 3.6 2.8 6.2 3.3.8.2 1.8.3 3 .3 4.4 0 7.5-2.3 10.4-6.5 2.3 3.7 6.6 5.7 11.6 5.7.3 0 .5.2.9.2 2.6 0 6-.9 8.7-5.4 2.3 4.1 6.5 6.5 11.5 6.5 4.4 0 8.3-1.8 9-2.2l.2-.1c1.5-.8 2.7-1.5 3.7-2 3.3 1.8 8.3 3.7 14.5 3.7 1.1 0 2.1 0 3.2-.2h.6c13-2.6 21.5-5.7 26.6-8.1 3.5 4 9.2 7.8 17.2 8.4.9.1 1.8.1 2.7.1 6.6 0 11.9-1.9 15.8-3.9 1.2 1.3 2.8 2.5 4.8 3.3 1.2.5 2.5.7 3.7.7 8.1 0 11.9-9.6 12.9-12.9l1.9-5.2c1.7 1.8 3.9 3.3 6.7 4.1 1.5.4 3.2.7 4.8.7 8.9 0 17.5-6.3 18.8-7.4 2.3-2.3 4.9-6.5 4.4-12.2\"></path></g><g><path fill=\"#E24B31\" d=\"M174.35 245.713s-1.1-4 3.1-11.6 7.4-3.5 7.4-3.5 3.6 3.9-.5 9.7c-4.1 5.8-10 5.4-10 5.4m-32.1 5.5c-4.8 12.5-16.4 7.4-16.4 7.4s-1.3-4.5 2.5-17 12.6-7.6 12.6-7.6 6.1 4.7 1.3 17.2m-8.7-52.5s7.2-18.9 9-9.7c1.8 9.2-15.2 36.5-15.2 36.5.2-6.1 6.2-26.8 6.2-26.8m-103.5 47c.3-12.1 8.2-17.4 11-14.8 2.8 2.6 1.8 8.4-3.5 11.9-5.1 3.6-7.5 2.9-7.5 2.9m219.3-2c-.4-4.1-4.1-2.6-4.1-2.6s-5.9 4.6-11.1 4.1c-5.2-.5-3.5-12.1-3.5-12.1s1.1-10.7-1.9-11.6c-3.1-.9-6.8 2.8-6.8 2.8s-4.7 5.2-6.9 11.8l-.6.2s.7-11.6-.1-14.3c-.6-1.3-6.2-1.2-7.1 1.1-.9 2.3-5.4 18.6-5.7 25.5 0 0-8.8 7.4-16.4 8.7-7.7 1.2-9.5-3.6-9.5-3.6s20.8-5.8 20.1-22.4c-.7-16.6-16.8-10.5-18.6-9.1-1.8 1.3-11.1 7-13.9 22.6-.1.5-.3 2.9-.3 2.9s-8.1 5.4-12.5 6.8c0 0 12.5-21.1-2.8-30.7-6.9-4.2-12.5 4.6-12.5 4.6s20.7-23 16.1-42.5c-2.2-9.3-6.8-10.3-11.1-8.8-6.5 2.6-8.9 6.3-8.9 6.3s-8.4 12.1-10.3 30.2-4.8 39.8-4.8 39.8-4 3.9-7.6 4.1c-3.7.2-2-10.9-2-10.9s2.8-16.9 2.6-19.8-.4-4.4-3.8-5.4c-3.3-1-7 3.3-7 3.3s-9.7 14.7-10.5 16.9l-.5.9-.5-.6s6.8-20 .3-20.3c-6.5-.3-10.8 7.1-10.8 7.1s-7.4 12.5-7.7 13.9l-.5-.6s3.1-14.5 2.5-18.1c-.6-3.6-4-2.8-4-2.8s-4.3-.5-5.4 2.3c-1.1 2.8-5.2 21-5.7 26.8 0 0-10.7 7.7-17.7 7.7-7 .1-6.3-4.5-6.3-4.5s25.8-8.8 18.8-26.3c-3.2-4.5-6.8-5.9-12-5.8-5.2.1-11.3 3.3-15.5 12.6-2 4.5-2.8 8.7-2.8 11.9 0 0-4.8.9-7.3-1.1s-3.9 0-3.9 0-4.3 6.1-.1 7.7c4.2 1.6 10.6 3.2 10.6 3.2.6 2.6 2.3 7 7.4 10.8 7.6 5.8 22.3-.9 22.3-.9l6-3.6s.2 5.4 4.6 6.2c4.4.8 6.2-.1 13.9-18.6 4.5-9.5 4.8-9 4.8-9l.5-.1s-3.5 18.1-2.1 23 7.1 4.4 7.1 4.4 3.2 1.1 5.7-7.9c2.6-9 7.4-18.4 7.4-18.4h.6s-2.1 18.1 1.1 24c3.3 5.9 11.7 1.8 11.7 1.8s5.9-3.1 6.8-4c0 0 7 5.9 16.9 4.8 22.1-4.4 30-10.3 30-10.3s3.8 9.6 15.6 10.5c13.5 1 20.8-7.5 20.8-7.5s-.1 5.5 4.6 7.4c4.7 1.9 7.9-8.3 7.9-8.3l7.9-21.1h.7s.4 13.5 8.2 15.7c7.8 2.2 17.9-5.6 17.9-5.6s2.2-1.1 1.7-5.2\"></path></g></svg>"
 
 /***/ }),
 
-/***/ 112:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseSet = __webpack_require__(113);
-
-/**
- * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
- * it's created. Arrays are created for missing index properties while objects
- * are created for all other missing properties. Use `_.setWith` to customize
- * `path` creation.
- *
- * **Note:** This method mutates `object`.
- *
- * @static
- * @memberOf _
- * @since 3.7.0
- * @category Object
- * @param {Object} object The object to modify.
- * @param {Array|string} path The path of the property to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns `object`.
- * @example
- *
- * var object = { 'a': [{ 'b': { 'c': 3 } }] };
- *
- * _.set(object, 'a[0].b.c', 4);
- * console.log(object.a[0].b.c);
- * // => 4
- *
- * _.set(object, ['x', '0', 'y', 'z'], 5);
- * console.log(object.x[0].y.z);
- * // => 5
- */
-function set(object, path, value) {
-  return object == null ? object : baseSet(object, path, value);
-}
-
-module.exports = set;
-
-
-/***/ }),
-
-/***/ 113:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assignValue = __webpack_require__(114),
-    castPath = __webpack_require__(69),
-    isIndex = __webpack_require__(117),
-    isObject = __webpack_require__(84),
-    toKey = __webpack_require__(111);
-
-/**
- * The base implementation of `_.set`.
- *
- * @private
- * @param {Object} object The object to modify.
- * @param {Array|string} path The path of the property to set.
- * @param {*} value The value to set.
- * @param {Function} [customizer] The function to customize path creation.
- * @returns {Object} Returns `object`.
- */
-function baseSet(object, path, value, customizer) {
-  if (!isObject(object)) {
-    return object;
-  }
-  path = castPath(path, object);
-
-  var index = -1,
-      length = path.length,
-      lastIndex = length - 1,
-      nested = object;
-
-  while (nested != null && ++index < length) {
-    var key = toKey(path[index]),
-        newValue = value;
-
-    if (index != lastIndex) {
-      var objValue = nested[key];
-      newValue = customizer ? customizer(objValue, key, nested) : undefined;
-      if (newValue === undefined) {
-        newValue = isObject(objValue)
-          ? objValue
-          : (isIndex(path[index + 1]) ? [] : {});
-      }
-    }
-    assignValue(nested, key, newValue);
-    nested = nested[key];
-  }
-  return object;
-}
-
-module.exports = baseSet;
-
-
-/***/ }),
-
-/***/ 114:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseAssignValue = __webpack_require__(115),
-    eq = __webpack_require__(97);
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Assigns `value` to `key` of `object` if the existing value is not equivalent
- * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
- * for equality comparisons.
- *
- * @private
- * @param {Object} object The object to modify.
- * @param {string} key The key of the property to assign.
- * @param {*} value The value to assign.
- */
-function assignValue(object, key, value) {
-  var objValue = object[key];
-  if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
-      (value === undefined && !(key in object))) {
-    baseAssignValue(object, key, value);
-  }
-}
-
-module.exports = assignValue;
-
-
-/***/ }),
-
-/***/ 115:
-/***/ (function(module, exports, __webpack_require__) {
-
-var defineProperty = __webpack_require__(116);
-
-/**
- * The base implementation of `assignValue` and `assignMergeValue` without
- * value checks.
- *
- * @private
- * @param {Object} object The object to modify.
- * @param {string} key The key of the property to assign.
- * @param {*} value The value to assign.
- */
-function baseAssignValue(object, key, value) {
-  if (key == '__proto__' && defineProperty) {
-    defineProperty(object, key, {
-      'configurable': true,
-      'enumerable': true,
-      'value': value,
-      'writable': true
-    });
-  } else {
-    object[key] = value;
-  }
-}
-
-module.exports = baseAssignValue;
-
-
-/***/ }),
-
-/***/ 116:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getNative = __webpack_require__(81);
-
-var defineProperty = (function() {
-  try {
-    var func = getNative(Object, 'defineProperty');
-    func({}, '', {});
-    return func;
-  } catch (e) {}
-}());
-
-module.exports = defineProperty;
-
-
-/***/ }),
-
-/***/ 117:
-/***/ (function(module, exports) {
-
-/** Used as references for various `Number` constants. */
-var MAX_SAFE_INTEGER = 9007199254740991;
-
-/** Used to detect unsigned integer values. */
-var reIsUint = /^(?:0|[1-9]\d*)$/;
-
-/**
- * Checks if `value` is a valid array-like index.
- *
- * @private
- * @param {*} value The value to check.
- * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
- * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
- */
-function isIndex(value, length) {
-  var type = typeof value;
-  length = length == null ? MAX_SAFE_INTEGER : length;
-
-  return !!length &&
-    (type == 'number' ||
-      (type != 'symbol' && reIsUint.test(value))) &&
-        (value > -1 && value % 1 == 0 && value < length);
-}
-
-module.exports = isIndex;
-
-
-/***/ }),
-
 /***/ 1174:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 400 400\" xml:space=\"preserve\" id=\"svg2\" version=\"1.1\"><metadata id=\"metadata8\"><rdf:RDF><cc:Work rdf:about><dc:format>image/svg+xml</dc:format><dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"></dc></cc:Work></rdf:RDF></metadata><defs id=\"defs6\"></defs><g transform=\"matrix(1.3333333,0,0,-1.3333333,0,400)\" id=\"g10\"><g transform=\"translate(178.0626,235.0086)\" id=\"g12\"><path id=\"path14\" style=\"fill:#41b883;fill-opacity:1;fill-rule:nonzero;stroke:none\" d=\"M 0,0 -22.669,-39.264 -45.338,0 h -75.491 L -22.669,-170.017 75.491,0 Z\"></path></g><g transform=\"translate(178.0626,235.0086)\" id=\"g16\"><path id=\"path18\" style=\"fill:#34495e;fill-opacity:1;fill-rule:nonzero;stroke:none\" d=\"M 0,0 -22.669,-39.264 -45.338,0 H -81.565 L -22.669,-102.01 36.227,0 Z\"></path></g></g></svg>"
 
 /***/ }),
 
 /***/ 118:
@@ -1455,16 +831,20 @@ module.exports = "<!-- This Source Code 
 /***/ }),
 
 /***/ 1355:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 const feature = __webpack_require__(1461);
 
 module.exports = feature;
 
 /***/ }),
 
 /***/ 1359:
 /***/ (function(module, exports, __webpack_require__) {
@@ -1867,52 +1247,16 @@ EventEmitter.prototype = {
         }
       }
     }
   }
 };
 
 /***/ }),
 
-/***/ 14:
-/***/ (function(module, exports) {
-
-/**
- * Checks if `value` is object-like. A value is object-like if it's not `null`
- * and has a `typeof` result of "object".
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
- * @example
- *
- * _.isObjectLike({});
- * // => true
- *
- * _.isObjectLike([1, 2, 3]);
- * // => true
- *
- * _.isObjectLike(_.noop);
- * // => false
- *
- * _.isObjectLike(null);
- * // => false
- */
-function isObjectLike(value) {
-  return value != null && typeof value == 'object';
-}
-
-module.exports = isObjectLike;
-
-
-/***/ }),
-
 /***/ 1413:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -2065,102 +1409,55 @@ module.exports = SplitBox;
 /***/ }),
 
 /***/ 1461:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
-const pick = __webpack_require__(67);
-const put = __webpack_require__(112);
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const { get: pick, set: put } = __webpack_require__(2);
 const fs = __webpack_require__(118);
 const path = __webpack_require__(119);
 
 let config;
-
-const flag = __webpack_require__(52);
-
-function isBrowser() {
-  return typeof window == "object" && typeof module == "undefined";
-}
-
 /**
  * Gets a config value for a given key
  * e.g "chrome.webSocketPort"
  */
 function getValue(key) {
   return pick(config, key);
 }
 
 function setValue(key, value) {
   return put(config, key, value);
 }
 
-function isEnabled(key) {
-  return config.features && typeof config.features[key] == "object" ? config.features[key].enabled : config.features[key];
-}
-
-function isDevelopment() {
-  if (isBrowser()) {
-    if (true) {
-      return false;
-    }
-    const href = window.location ? window.location.href : "";
-    return href.match(/^file:/) || href.match(/localhost:/);
-  }
-
-  if (isFirefoxPanel()) {
-    // Default to production if compiling for the Firefox panel
-    return "production" === "development";
-  }
-  return "production" !== "production";
-}
-
-function isTesting() {
-  return flag.testing;
-}
-
-function isFirefoxPanel() {
-  return "firefox-panel" == "firefox-panel";
-}
-
-function isApplication() {
-  return "firefox-panel" == "application";
-}
-
-function isFirefox() {
-  return (/firefox/i.test(navigator.userAgent)
-  );
-}
-
 function setConfig(value) {
   config = value;
 }
 
 function getConfig() {
   return config;
 }
 
 function updateLocalConfig(relativePath) {
   const localConfigPath = path.resolve(relativePath, "../configs/local.json");
   const output = JSON.stringify(config, null, 2);
   fs.writeFileSync(localConfigPath, output, { flag: "w" });
   return output;
 }
 
 module.exports = {
-  isEnabled,
   getValue,
   setValue,
-  isDevelopment,
-  isTesting,
-  isFirefoxPanel,
-  isApplication,
-  isFirefox,
   getConfig,
   setConfig,
   updateLocalConfig
 };
 
 /***/ }),
 
 /***/ 1464:
@@ -5446,16 +4743,23 @@ function extractSVGProps(src) {
 
 /***/ 1808:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg viewBox=\"0 0 256 247\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" preserveAspectRatio=\"xMidYMid\"><defs><radialGradient cx=\"78.7636112%\" cy=\"37.8476394%\" fx=\"78.7636112%\" fy=\"37.8476394%\" r=\"89.8725577%\" id=\"radialGradient-1\"><stop stop-color=\"#F80090\" offset=\"0%\"></stop><stop stop-color=\"#4D008E\" offset=\"100%\"></stop></radialGradient><radialGradient cx=\"68.7389016%\" cy=\"4.39833672%\" fx=\"68.7389016%\" fy=\"4.39833672%\" r=\"81.7284786%\" id=\"radialGradient-2\"><stop stop-color=\"#57008E\" offset=\"0%\"></stop><stop stop-color=\"#5C008E\" offset=\"29.1746283%\"></stop><stop stop-color=\"#F80090\" offset=\"100%\"></stop></radialGradient><linearGradient x1=\"18.2386532%\" y1=\"0%\" x2=\"81.1591125%\" y2=\"84.3374763%\" id=\"linearGradient-3\"><stop stop-color=\"#F70090\" offset=\"0%\"></stop><stop stop-color=\"#E50090\" offset=\"66.9712865%\"></stop><stop stop-color=\"#D6008F\" stop-opacity=\"0.2\" offset=\"82.7147533%\"></stop><stop stop-color=\"#C10090\" stop-opacity=\"0\" offset=\"100%\"></stop></linearGradient><linearGradient x1=\"64.9060589%\" y1=\"71.5585538%\" x2=\"44.2897699%\" y2=\"50%\" id=\"linearGradient-4\"><stop stop-color=\"#B2008F\" stop-opacity=\"0.151340138\" offset=\"0%\"></stop><stop stop-color=\"#F70090\" stop-opacity=\"0.4\" offset=\"40.0350765%\"></stop><stop stop-color=\"#F60090\" stop-opacity=\"0.891668\" offset=\"64.8995536%\"></stop><stop stop-color=\"#FF0090\" offset=\"100%\"></stop></linearGradient></defs><g><path d=\"M16.6852208,157.125328 C3.56690702,87.3798324 38.2363025,20.1145078 117.808706,11.1662199 C106.835616,-0.558801732 91.8452087,-0.646905628 84.9481697,0.779380087 C72.770288,4.66044372 73.1525932,12.540855 59.3390152,22.7199675 C45.6064437,30.5634307 38.7094156,24.5568182 28.7057455,32.6879515 C18.7234849,40.7583874 25.6888528,59.2851732 21.5022823,62.8870857 C17.3464381,70.0905489 4.45500952,76.5077264 2.10834286,85.6062545 C0.168948918,97.2420641 7.37241212,105.553752 7.09535584,115.527778 C7.92652468,123.839467 -1.17920693,128.539449 0.129052814,135.275796 C4.0477368,146.281025 11.600845,152.904887 15.1615723,155.958047 C15.9781085,156.533531 16.8404881,157.95083 16.6852208,157.125328 L16.6852208,157.125328 Z\" fill=\"#FF0090\"></path><path d=\"M158.275491,60.578542 C155.368486,60.578542 153.011422,58.2214776 153.011422,55.3144727 C153.011422,52.4074679 155.368486,50.0504035 158.275491,50.0504035 C161.182496,50.0504035 163.53956,52.4074679 163.53956,55.3144727 C163.53956,58.2214776 161.182496,60.578542 158.275491,60.578542 L158.275491,60.578542 Z M19.7566405,164.732808 C7.1500258,104.116773 46.1602355,53.4676156 121.704062,78.4026805 C166.031404,104.334594 221.793282,102.646102 224.307422,85.8832 C230.514061,65.7878769 196.047681,24.3767065 144.515214,13.5715117 C42.2814476,-6.37654026 -12.8335943,104.116774 19.7566405,164.732808 L19.7566405,164.732808 Z\" fill=\"url(#radialGradient-1)\"></path><path d=\"M187.458604,171.493257 C202.639072,173.137863 217.048769,169.494573 230.402327,158.61014 C210.228197,181.112651 185.002777,192.426521 156.059262,195.505171 C169.878829,207.254019 183.20579,212.546348 195.955366,210.281136 C160.528734,220.05679 130.847947,209.296529 94.7424273,173.340673 C92.8517347,183.020022 103.074741,198.100667 113.611745,207.727264 C52.4742909,181.221845 47.1143627,98.6544556 121.66531,78.3442237 C44.3844415,41.214641 0.686373501,113.357693 22.1558444,172.485931 C43.1623368,218.026693 99.1402667,253.085223 160.492163,245.3753 C190.292928,241.7251 234.79401,221.178935 252.973664,172.485931 C240.160919,183.983766 217.257941,193.997836 207.037617,194.765984 C241.628648,177.478781 260.301586,148.103896 255.060336,107.955387 C247.895106,125.013742 238.441392,138.114625 226.616076,147.112305 C251.735653,107.955387 247.425219,87.716426 228.832526,65.4732398 C242.131228,102.044668 224.928249,142.633967 187.458604,171.493257 L187.458604,171.493257 Z\" fill=\"url(#radialGradient-2)\"></path><path d=\"M169.707072,213.625541 C167.082407,213.13513 175.656929,217.098842 159.079366,212.710316 C142.501804,208.32179 125.622502,204.092744 94.7424273,173.340673 C92.8517347,183.020022 103.074741,198.100667 113.611745,207.727264 C142.056275,227.564927 122.711866,218.286797 166.051946,233.269481 C169.52976,226.346862 169.707072,220.195346 169.707072,213.625541 L169.707072,213.625541 Z\" fill=\"url(#linearGradient-3)\"></path><path d=\"M114.601372,57.8510108 C114.601372,57.8510108 118.369452,52.2893628 119.836219,49.7810251 C121.633641,46.7072319 124.393939,41.104618 124.393939,41.104618 C124.393939,41.104618 95.389611,31.6417749 88.2716448,30.4871665 C66.1450215,36.2308801 66.0645022,45.5009559 78.435065,59.690116 C79.8114806,61.2693368 114.601372,57.8510108 114.601372,57.8510108 L114.601372,57.8510108 Z\" fill=\"url(#linearGradient-4)\"></path></g></svg>"
 
 /***/ }),
 
+/***/ 2:
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_2__;
+
+/***/ }),
+
 /***/ 22:
 /***/ (function(module, exports) {
 
 module.exports = __WEBPACK_EXTERNAL_MODULE_22__;
 
 /***/ }),
 
 /***/ 2250:
@@ -9961,555 +9265,28 @@ module.exports = __WEBPACK_EXTERNAL_MODU
 
 /***/ 52:
 /***/ (function(module, exports) {
 
 module.exports = __WEBPACK_EXTERNAL_MODULE_52__;
 
 /***/ }),
 
-/***/ 6:
-/***/ (function(module, exports, __webpack_require__) {
-
-var Symbol = __webpack_require__(7),
-    getRawTag = __webpack_require__(10),
-    objectToString = __webpack_require__(11);
-
-/** `Object#toString` result references. */
-var nullTag = '[object Null]',
-    undefinedTag = '[object Undefined]';
-
-/** Built-in value references. */
-var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
-
-/**
- * The base implementation of `getTag` without fallbacks for buggy environments.
- *
- * @private
- * @param {*} value The value to query.
- * @returns {string} Returns the `toStringTag`.
- */
-function baseGetTag(value) {
-  if (value == null) {
-    return value === undefined ? undefinedTag : nullTag;
-  }
-  return (symToStringTag && symToStringTag in Object(value))
-    ? getRawTag(value)
-    : objectToString(value);
-}
-
-module.exports = baseGetTag;
-
-
-/***/ }),
-
 /***/ 66:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 exports.decode = exports.parse = __webpack_require__(121);
 exports.encode = exports.stringify = __webpack_require__(122);
 
 
 /***/ }),
 
-/***/ 67:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseGet = __webpack_require__(68);
-
-/**
- * Gets the value at `path` of `object`. If the resolved value is
- * `undefined`, the `defaultValue` is returned in its place.
- *
- * @static
- * @memberOf _
- * @since 3.7.0
- * @category Object
- * @param {Object} object The object to query.
- * @param {Array|string} path The path of the property to get.
- * @param {*} [defaultValue] The value returned for `undefined` resolved values.
- * @returns {*} Returns the resolved value.
- * @example
- *
- * var object = { 'a': [{ 'b': { 'c': 3 } }] };
- *
- * _.get(object, 'a[0].b.c');
- * // => 3
- *
- * _.get(object, ['a', '0', 'b', 'c']);
- * // => 3
- *
- * _.get(object, 'a.b.c', 'default');
- * // => 'default'
- */
-function get(object, path, defaultValue) {
-  var result = object == null ? undefined : baseGet(object, path);
-  return result === undefined ? defaultValue : result;
-}
-
-module.exports = get;
-
-
-/***/ }),
-
-/***/ 68:
-/***/ (function(module, exports, __webpack_require__) {
-
-var castPath = __webpack_require__(69),
-    toKey = __webpack_require__(111);
-
-/**
- * The base implementation of `_.get` without support for default values.
- *
- * @private
- * @param {Object} object The object to query.
- * @param {Array|string} path The path of the property to get.
- * @returns {*} Returns the resolved value.
- */
-function baseGet(object, path) {
-  path = castPath(path, object);
-
-  var index = 0,
-      length = path.length;
-
-  while (object != null && index < length) {
-    object = object[toKey(path[index++])];
-  }
-  return (index && index == length) ? object : undefined;
-}
-
-module.exports = baseGet;
-
-
-/***/ }),
-
-/***/ 69:
-/***/ (function(module, exports, __webpack_require__) {
-
-var isArray = __webpack_require__(70),
-    isKey = __webpack_require__(71),
-    stringToPath = __webpack_require__(73),
-    toString = __webpack_require__(108);
-
-/**
- * Casts `value` to a path array if it's not one.
- *
- * @private
- * @param {*} value The value to inspect.
- * @param {Object} [object] The object to query keys on.
- * @returns {Array} Returns the cast property path array.
- */
-function castPath(value, object) {
-  if (isArray(value)) {
-    return value;
-  }
-  return isKey(value, object) ? [value] : stringToPath(toString(value));
-}
-
-module.exports = castPath;
-
-
-/***/ }),
-
-/***/ 7:
-/***/ (function(module, exports, __webpack_require__) {
-
-var root = __webpack_require__(8);
-
-/** Built-in value references. */
-var Symbol = root.Symbol;
-
-module.exports = Symbol;
-
-
-/***/ }),
-
-/***/ 70:
-/***/ (function(module, exports) {
-
-/**
- * Checks if `value` is classified as an `Array` object.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an array, else `false`.
- * @example
- *
- * _.isArray([1, 2, 3]);
- * // => true
- *
- * _.isArray(document.body.children);
- * // => false
- *
- * _.isArray('abc');
- * // => false
- *
- * _.isArray(_.noop);
- * // => false
- */
-var isArray = Array.isArray;
-
-module.exports = isArray;
-
-
-/***/ }),
-
-/***/ 71:
-/***/ (function(module, exports, __webpack_require__) {
-
-var isArray = __webpack_require__(70),
-    isSymbol = __webpack_require__(72);
-
-/** Used to match property names within property paths. */
-var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
-    reIsPlainProp = /^\w*$/;
-
-/**
- * Checks if `value` is a property name and not a property path.
- *
- * @private
- * @param {*} value The value to check.
- * @param {Object} [object] The object to query keys on.
- * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
- */
-function isKey(value, object) {
-  if (isArray(value)) {
-    return false;
-  }
-  var type = typeof value;
-  if (type == 'number' || type == 'symbol' || type == 'boolean' ||
-      value == null || isSymbol(value)) {
-    return true;
-  }
-  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
-    (object != null && value in Object(object));
-}
-
-module.exports = isKey;
-
-
-/***/ }),
-
-/***/ 72:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseGetTag = __webpack_require__(6),
-    isObjectLike = __webpack_require__(14);
-
-/** `Object#toString` result references. */
-var symbolTag = '[object Symbol]';
-
-/**
- * Checks if `value` is classified as a `Symbol` primitive or object.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
- * @example
- *
- * _.isSymbol(Symbol.iterator);
- * // => true
- *
- * _.isSymbol('abc');
- * // => false
- */
-function isSymbol(value) {
-  return typeof value == 'symbol' ||
-    (isObjectLike(value) && baseGetTag(value) == symbolTag);
-}
-
-module.exports = isSymbol;
-
-
-/***/ }),
-
-/***/ 73:
-/***/ (function(module, exports, __webpack_require__) {
-
-var memoizeCapped = __webpack_require__(74);
-
-/** Used to match property names within property paths. */
-var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
-
-/** Used to match backslashes in property paths. */
-var reEscapeChar = /\\(\\)?/g;
-
-/**
- * Converts `string` to a property path array.
- *
- * @private
- * @param {string} string The string to convert.
- * @returns {Array} Returns the property path array.
- */
-var stringToPath = memoizeCapped(function(string) {
-  var result = [];
-  if (string.charCodeAt(0) === 46 /* . */) {
-    result.push('');
-  }
-  string.replace(rePropName, function(match, number, quote, subString) {
-    result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));
-  });
-  return result;
-});
-
-module.exports = stringToPath;
-
-
-/***/ }),
-
-/***/ 74:
-/***/ (function(module, exports, __webpack_require__) {
-
-var memoize = __webpack_require__(75);
-
-/** Used as the maximum memoize cache size. */
-var MAX_MEMOIZE_SIZE = 500;
-
-/**
- * A specialized version of `_.memoize` which clears the memoized function's
- * cache when it exceeds `MAX_MEMOIZE_SIZE`.
- *
- * @private
- * @param {Function} func The function to have its output memoized.
- * @returns {Function} Returns the new memoized function.
- */
-function memoizeCapped(func) {
-  var result = memoize(func, function(key) {
-    if (cache.size === MAX_MEMOIZE_SIZE) {
-      cache.clear();
-    }
-    return key;
-  });
-
-  var cache = result.cache;
-  return result;
-}
-
-module.exports = memoizeCapped;
-
-
-/***/ }),
-
-/***/ 75:
-/***/ (function(module, exports, __webpack_require__) {
-
-var MapCache = __webpack_require__(76);
-
-/** Error message constants. */
-var FUNC_ERROR_TEXT = 'Expected a function';
-
-/**
- * Creates a function that memoizes the result of `func`. If `resolver` is
- * provided, it determines the cache key for storing the result based on the
- * arguments provided to the memoized function. By default, the first argument
- * provided to the memoized function is used as the map cache key. The `func`
- * is invoked with the `this` binding of the memoized function.
- *
- * **Note:** The cache is exposed as the `cache` property on the memoized
- * function. Its creation may be customized by replacing the `_.memoize.Cache`
- * constructor with one whose instances implement the
- * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
- * method interface of `clear`, `delete`, `get`, `has`, and `set`.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Function
- * @param {Function} func The function to have its output memoized.
- * @param {Function} [resolver] The function to resolve the cache key.
- * @returns {Function} Returns the new memoized function.
- * @example
- *
- * var object = { 'a': 1, 'b': 2 };
- * var other = { 'c': 3, 'd': 4 };
- *
- * var values = _.memoize(_.values);
- * values(object);
- * // => [1, 2]
- *
- * values(other);
- * // => [3, 4]
- *
- * object.a = 2;
- * values(object);
- * // => [1, 2]
- *
- * // Modify the result cache.
- * values.cache.set(object, ['a', 'b']);
- * values(object);
- * // => ['a', 'b']
- *
- * // Replace `_.memoize.Cache`.
- * _.memoize.Cache = WeakMap;
- */
-function memoize(func, resolver) {
-  if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
-    throw new TypeError(FUNC_ERROR_TEXT);
-  }
-  var memoized = function() {
-    var args = arguments,
-        key = resolver ? resolver.apply(this, args) : args[0],
-        cache = memoized.cache;
-
-    if (cache.has(key)) {
-      return cache.get(key);
-    }
-    var result = func.apply(this, args);
-    memoized.cache = cache.set(key, result) || cache;
-    return result;
-  };
-  memoized.cache = new (memoize.Cache || MapCache);
-  return memoized;
-}
-
-// Expose `MapCache`.
-memoize.Cache = MapCache;
-
-module.exports = memoize;
-
-
-/***/ }),
-
-/***/ 76:
-/***/ (function(module, exports, __webpack_require__) {
-
-var mapCacheClear = __webpack_require__(77),
-    mapCacheDelete = __webpack_require__(102),
-    mapCacheGet = __webpack_require__(105),
-    mapCacheHas = __webpack_require__(106),
-    mapCacheSet = __webpack_require__(107);
-
-/**
- * Creates a map cache object to store key-value pairs.
- *
- * @private
- * @constructor
- * @param {Array} [entries] The key-value pairs to cache.
- */
-function MapCache(entries) {
-  var index = -1,
-      length = entries == null ? 0 : entries.length;
-
-  this.clear();
-  while (++index < length) {
-    var entry = entries[index];
-    this.set(entry[0], entry[1]);
-  }
-}
-
-// Add methods to `MapCache`.
-MapCache.prototype.clear = mapCacheClear;
-MapCache.prototype['delete'] = mapCacheDelete;
-MapCache.prototype.get = mapCacheGet;
-MapCache.prototype.has = mapCacheHas;
-MapCache.prototype.set = mapCacheSet;
-
-module.exports = MapCache;
-
-
-/***/ }),
-
-/***/ 77:
-/***/ (function(module, exports, __webpack_require__) {
-
-var Hash = __webpack_require__(78),
-    ListCache = __webpack_require__(93),
-    Map = __webpack_require__(101);
-
-/**
- * Removes all key-value entries from the map.
- *
- * @private
- * @name clear
- * @memberOf MapCache
- */
-function mapCacheClear() {
-  this.size = 0;
-  this.__data__ = {
-    'hash': new Hash,
-    'map': new (Map || ListCache),
-    'string': new Hash
-  };
-}
-
-module.exports = mapCacheClear;
-
-
-/***/ }),
-
-/***/ 78:
-/***/ (function(module, exports, __webpack_require__) {
-
-var hashClear = __webpack_require__(79),
-    hashDelete = __webpack_require__(89),
-    hashGet = __webpack_require__(90),
-    hashHas = __webpack_require__(91),
-    hashSet = __webpack_require__(92);
-
-/**
- * Creates a hash object.
- *
- * @private
- * @constructor
- * @param {Array} [entries] The key-value pairs to cache.
- */
-function Hash(entries) {
-  var index = -1,
-      length = entries == null ? 0 : entries.length;
-
-  this.clear();
-  while (++index < length) {
-    var entry = entries[index];
-    this.set(entry[0], entry[1]);
-  }
-}
-
-// Add methods to `Hash`.
-Hash.prototype.clear = hashClear;
-Hash.prototype['delete'] = hashDelete;
-Hash.prototype.get = hashGet;
-Hash.prototype.has = hashHas;
-Hash.prototype.set = hashSet;
-
-module.exports = Hash;
-
-
-/***/ }),
-
-/***/ 79:
-/***/ (function(module, exports, __webpack_require__) {
-
-var nativeCreate = __webpack_require__(80);
-
-/**
- * Removes all key-value entries from the hash.
- *
- * @private
- * @name clear
- * @memberOf Hash
- */
-function hashClear() {
-  this.__data__ = nativeCreate ? nativeCreate(null) : {};
-  this.size = 0;
-}
-
-module.exports = hashClear;
-
-
-/***/ }),
-
 /***/ 792:
 /***/ (function(module, exports) {
 
 var g;
 
 // This works in non-strict mode
 g = (function() {
 	return this;
@@ -10557,674 +9334,37 @@ module.exports = function(module) {
 		module.webpackPolyfill = 1;
 	}
 	return module;
 };
 
 
 /***/ }),
 
-/***/ 8:
-/***/ (function(module, exports, __webpack_require__) {
-
-var freeGlobal = __webpack_require__(9);
-
-/** Detect free variable `self`. */
-var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
-
-/** Used as a reference to the global object. */
-var root = freeGlobal || freeSelf || Function('return this')();
-
-module.exports = root;
-
-
-/***/ }),
-
-/***/ 80:
-/***/ (function(module, exports, __webpack_require__) {
-
-var getNative = __webpack_require__(81);
-
-/* Built-in method references that are verified to be native. */
-var nativeCreate = getNative(Object, 'create');
-
-module.exports = nativeCreate;
-
-
-/***/ }),
-
 /***/ 806:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 256 256\"><defs><style>.cls-1{isolation:isolate;}.cls-17,.cls-2,.cls-25{fill:none;}.cls-17,.cls-2{stroke-miterlimit:10;}.cls-2{stroke-width:0.75px;stroke:url(#linear-gradient);}.cls-3{fill:url(#linear-gradient-2);}.cls-4{fill:#f15a24;}.cls-5{fill:#ed1c24;}.cls-6{fill:#c1272d;}.cls-7{fill:url(#linear-gradient-3);}.cls-8{fill:url(#linear-gradient-4);}.cls-9{fill:url(#linear-gradient-5);}.cls-10{fill:url(#linear-gradient-6);}.cls-11{opacity:0.49;fill:url(#linear-gradient-7);}.cls-12{fill:url(#linear-gradient-8);}.cls-13{fill:#2db5f9;}.cls-13,.cls-14{mix-blend-mode:screen;}.cls-14{fill:#5fd2ff;}.cls-15{fill:#219058;}.cls-16{fill:url(#linear-gradient-9);}.cls-17{stroke:#fff;stroke-width:1.87px;}.cls-18{fill:#f7b852;}.cls-19{fill:#ff8431;}.cls-20{fill:#fffb69;}.cls-21{fill:#44c688;}.cls-22{fill:#29b36e;}.cls-23{fill:#6fd191;}.cls-24{fill:#c83ad7;}.cls-26{fill:#fba9ff;}.cls-27{fill:#ff737d;}.cls-28{fill:#fdc666;}</style><linearGradient id=\"linear-gradient\" x1=\"67.45\" y1=\"154.72\" x2=\"67.29\" y2=\"155.43\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\" stop-color=\"#ff1d25\" stop-opacity=\"0.5\"></stop><stop offset=\"0.06\" stop-color=\"#ff1d25\" stop-opacity=\"0.54\"></stop><stop offset=\"0.37\" stop-color=\"#ff1d25\" stop-opacity=\"0.74\"></stop><stop offset=\"0.64\" stop-color=\"#ff1d25\" stop-opacity=\"0.88\"></stop><stop offset=\"0.86\" stop-color=\"#ff1d25\" stop-opacity=\"0.97\"></stop><stop offset=\"1\" stop-color=\"#ff1d25\"></stop></linearGradient><linearGradient id=\"linear-gradient-2\" x1=\"73.09\" y1=\"170.74\" x2=\"73.09\" y2=\"153.5\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\" stop-color=\"#ffdd42\"></stop><stop offset=\"1\" stop-color=\"#fb784b\"></stop></linearGradient><linearGradient id=\"linear-gradient-3\" x1=\"201.52\" y1=\"95.13\" x2=\"207.88\" y2=\"89.89\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\" stop-color=\"#5bcb99\"></stop><stop offset=\"1\" stop-color=\"#85a8e8\"></stop></linearGradient><linearGradient id=\"linear-gradient-4\" x1=\"81.17\" y1=\"158.3\" x2=\"279.32\" y2=\"55.49\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\" stop-color=\"#34e28b\"></stop><stop offset=\"1\"></stop></linearGradient><linearGradient id=\"linear-gradient-5\" x1=\"117.57\" y1=\"178.22\" x2=\"133.15\" y2=\"178.22\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\" stop-color=\"#c297ff\"></stop><stop offset=\"1\" stop-color=\"#ae31bb\"></stop></linearGradient><linearGradient id=\"linear-gradient-6\" x1=\"54.05\" y1=\"253.29\" x2=\"251.08\" y2=\"99.63\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\"></stop><stop offset=\"1\" stop-color=\"#d23de2\"></stop></linearGradient><linearGradient id=\"linear-gradient-7\" x1=\"199.8\" y1=\"86.45\" x2=\"191.83\" y2=\"113.37\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\"></stop><stop offset=\"1\" stop-opacity=\"0\"></stop></linearGradient><linearGradient id=\"linear-gradient-8\" x1=\"126.87\" y1=\"190.63\" x2=\"182.9\" y2=\"204.2\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\" stop-color=\"#2db5f9\"></stop><stop offset=\"1\" stop-color=\"#092432\"></stop></linearGradient><linearGradient id=\"linear-gradient-9\" x1=\"83.08\" y1=\"49.55\" x2=\"46.06\" y2=\"151.24\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\"></stop><stop offset=\"0.21\" stop-color=\"#48080a\"></stop><stop offset=\"0.42\" stop-color=\"#891014\"></stop><stop offset=\"0.61\" stop-color=\"#bc151b\"></stop><stop offset=\"0.78\" stop-color=\"#e01a21\"></stop><stop offset=\"0.91\" stop-color=\"#f71c24\"></stop><stop offset=\"1\" stop-color=\"#ff1d25\"></stop></linearGradient></defs><title>dojo_square</title><g class=\"cls-1\"><g id=\"Layer_1\" data-name=\"Layer 1\"><line class=\"cls-2\" x1=\"67.37\" y1=\"155.08\" x2=\"67.37\" y2=\"155.08\"></line><path class=\"cls-3\" d=\"M42.28,150.4l.52.82A58,58,0,0,0,52,161.49a45.23,45.23,0,0,0,28.74,10.25c.65,0,1.31,0,2,0a67.32,67.32,0,0,0,21.13-5.26,67.38,67.38,0,0,1-9.09.83,36.92,36.92,0,0,1-27.44-12.17A66.82,66.82,0,0,1,42.28,150.4Z\"></path><path class=\"cls-4\" d=\"M80.79,80.88a45.4,45.4,0,0,1,38.89,21.94A37,37,0,0,0,84.43,94.7c8.29,4,19.66,7.08,35.28,8.15,0,0-.77-14.87-19.8-22.64-26.57-10.84-30.33-8.69-37.06-19.9a30.09,30.09,0,0,0,6,22.15A45.45,45.45,0,0,1,80.79,80.88Z\"></path><path class=\"cls-5\" d=\"M99.92,80.21c-9.1-3.71-15.52-5.9-20.3-7.62A33.4,33.4,0,0,0,84.54,81a45.42,45.42,0,0,1,35.13,21.78,36.87,36.87,0,0,0-20.54-9.34,109,109,0,0,0,20,9.32l.59,0S118.94,88,99.92,80.21Z\"></path><path class=\"cls-6\" d=\"M119.69,102.85h.1c.29-1.62,2.07-14.46-12.4-25.7C85.78,60.37,81.56,58.82,80.53,49.94a27.8,27.8,0,0,0-.91,22.65c4.78,1.72,11.21,3.91,20.3,7.62,19,7.77,19.8,22.64,19.8,22.64Z\"></path><path class=\"cls-7\" d=\"M185.28,88.22a33.64,33.64,0,0,1,22.08,8.23,29.8,29.8,0,0,1,19,8S208.22,78,176.19,89a41.72,41.72,0,0,0-8.2,4A33.64,33.64,0,0,1,185.28,88.22Z\"></path><path class=\"cls-8\" d=\"M185.28,88.22A33.62,33.62,0,0,0,168,93l.93-.56c-25.88,15.24-57.6,62.06-101.56,62.65h0a36.92,36.92,0,0,0,27.44,12.17,67.38,67.38,0,0,0,9.09-.83c28.6-11.79,56.09-40,68.55-53.64,11.56-12.67,24.22-17,34.91-16.34A33.64,33.64,0,0,0,185.28,88.22Z\"></path><path class=\"cls-9\" d=\"M118.48,179a20.94,20.94,0,0,0-.92,5.86,22.25,22.25,0,0,0,1,6.74,16.56,16.56,0,0,1,5.5-14.74c0-.17.09-.34.14-.51a20.37,20.37,0,0,1,8.91-11.47l-.08,0a37.84,37.84,0,0,0-4,1.53A20.87,20.87,0,0,0,118.48,179Z\"></path><path class=\"cls-10\" d=\"M234.26,129.11a42.41,42.41,0,0,0-7.94-24.76,29.82,29.82,0,0,0-19-7.9A33.69,33.69,0,0,1,219.06,122c0,11.34-4.12,24.3-17.45,31.28-19.42,10.16-49.21,5.33-68.54,11.6l.08,0a20.37,20.37,0,0,0-8.91,11.47c-.05.17-.09.34-.14.51h0c5.67-5,16.84-8.54,38.63-5.73,15.56,2,27.93,2.55,38.54-.5a41.2,41.2,0,0,0,25.23-17h0A42.41,42.41,0,0,0,234.26,129.11Z\"></path><path class=\"cls-11\" d=\"M234.26,129.11a42.41,42.41,0,0,0-7.94-24.76,29.82,29.82,0,0,0-19-7.9A33.69,33.69,0,0,1,219.06,122c0,11.34-4.12,24.3-17.45,31.28-19.42,10.16-49.21,5.33-68.54,11.6l.08,0a20.37,20.37,0,0,0-8.91,11.47c-.05.17-.09.34-.14.51h0c5.67-5,16.84-8.54,38.63-5.73,15.56,2,27.93,2.55,38.54-.5a41.2,41.2,0,0,0,25.23-17h0A42.41,42.41,0,0,0,234.26,129.11Z\"></path><path class=\"cls-12\" d=\"M137.8,201.88a20.44,20.44,0,0,1-13.68-25.12h0l0,.08a16.56,16.56,0,0,0-5.5,14.73,20.94,20.94,0,0,0,33.63,9.38A20.37,20.37,0,0,1,137.8,201.88Z\"></path><path class=\"cls-13\" d=\"M144.91,200.4c2.12-6.17,9-15.7,16.33-11.34,0,0,6,3.36,7.23-6.11,0,0,4.49,22.28-17.1,21.53,0,0,4.86-3.55,4.81-7.2A24.73,24.73,0,0,1,144.91,200.4Z\"></path><path class=\"cls-14\" d=\"M153.52,186.75c2.14-1.09,4.16-2.18,8.08-.44,3,1.35,6.88-3.94,3.56-8.66,0,0,.21,4.88-3.72,4.84A8.81,8.81,0,0,0,153.52,186.75Z\"></path><path class=\"cls-15\" d=\"M175.21,115.88c-5.17,7-12.75,12.95-13.64,14.39s1.5,6.11,5,6.45.82-1.36.52-3,1.06,1,5.27.42-1.53-2.2-1.14-4.33,4.74-6.17,6.47-10.25,4.7,0,3.18,3.18c-.6,1.26,4.81-3.54,2.08-7.21S178.22,111.77,175.21,115.88Z\"></path><path class=\"cls-15\" d=\"M160.47,131.28c-.76.73-3,2.37-3,2.37s2.19,3.05,5,3c0,0,.61-.29-.27-1.18S160.27,131.82,160.47,131.28Z\"></path><path class=\"cls-16\" d=\"M84.43,94.7c-7.35-3.56-12.27-7.88-15.54-12.24A45.42,45.42,0,0,0,42.28,150.4a66.82,66.82,0,0,0,25.09,4.67h0A37,37,0,0,1,84.43,94.7Z\"></path><line class=\"cls-17\" x1=\"67.37\" y1=\"155.08\" x2=\"67.37\" y2=\"155.08\"></line><path class=\"cls-18\" d=\"M84.52,81c2,2.91,7.81,7.94,14.63,12.44a36.87,36.87,0,0,1,20.52,9.33A45.42,45.42,0,0,0,84.52,81Z\"></path><path class=\"cls-19\" d=\"M84.52,81c-1.23-.1-2.48-.16-3.74-.16a45.45,45.45,0,0,0-11.89,1.58c3.27,4.36,8.19,8.67,15.54,12.24a36.72,36.72,0,0,1,14.72-1.22C92.33,89,86.54,83.95,84.52,81Z\"></path><path class=\"cls-20\" d=\"M109.73,91.38a33.29,33.29,0,0,0-12.21-7.29C100.46,89.66,103,91.38,109.73,91.38Z\"></path><path class=\"cls-6\" d=\"M96.89,67.66a63.16,63.16,0,0,1,6.54,4.58c.52.39-.93-3.55-2.62-4.3A7.5,7.5,0,0,0,96.89,67.66Z\"></path><path class=\"cls-6\" d=\"M105,73.37a70.75,70.75,0,0,1,6.5,4.64c.53.38-.9-3.56-2.57-4.33A7.5,7.5,0,0,0,105,73.37Z\"></path><path class=\"cls-6\" d=\"M112.55,79a19.59,19.59,0,0,1,3.52,4.39c.26.38.07-2.58-.92-3.42A5.28,5.28,0,0,0,112.55,79Z\"></path><path class=\"cls-21\" d=\"M77.55,151c-.2-.65,2.35-1.48,3-1.51a11.91,11.91,0,0,1,3.57,1.19,16.34,16.34,0,0,1-4.89,1A4.46,4.46,0,0,1,77.55,151Z\"></path><path class=\"cls-21\" d=\"M86.73,148.78c-.22-.51,1.75-1.38,2.29-1.46a9.58,9.58,0,0,1,3,.65,13.15,13.15,0,0,1-3.83,1.23A3.59,3.59,0,0,1,86.73,148.78Z\"></path><path class=\"cls-21\" d=\"M94.41,146c-.22-.4,1.32-1.29,1.76-1.41a7.92,7.92,0,0,1,2.48.27,10.87,10.87,0,0,1-3,1.35A3,3,0,0,1,94.41,146Z\"></path><path class=\"cls-21\" d=\"M100.52,143.19c-.23-.35,1.11-1.27,1.5-1.41a7.25,7.25,0,0,1,2.29.07,10,10,0,0,1-2.67,1.45A2.72,2.72,0,0,1,100.52,143.19Z\"></path><path class=\"cls-21\" d=\"M106.23,140.07c-.22-.29.9-1.16,1.24-1.3a6.31,6.31,0,0,1,2,0,8.66,8.66,0,0,1-2.25,1.39A2.36,2.36,0,0,1,106.23,140.07Z\"></path><path class=\"cls-21\" d=\"M68.34,151.69c-.11-.73,2.73-1.16,3.46-1.09a12.76,12.76,0,0,1,3.57,1.86,17.51,17.51,0,0,1-5.35.26A4.78,4.78,0,0,1,68.34,151.69Z\"></path><path class=\"cls-6\" d=\"M70.08,65.82c2,2.27,6.68,3.74,6.68,3.74A19,19,0,0,1,75.83,62c0-.18-5.75-.09-6.73-4.81C68.91,56.23,68.1,63.55,70.08,65.82Z\"></path><path class=\"cls-4\" d=\"M50.54,174.68a5.49,5.49,0,0,1,2.24-3.88l.19-.11a14,14,0,0,0-1.43-.25c-6.85-1-8.59,3.06-8.95,7.64,0,.26,0,.53,0,.78a8.31,8.31,0,0,1,7.89-4.2Z\"></path><path class=\"cls-4\" d=\"M58.88,173.19c-6.81-4.13-10.63-4.43-12.15,7.14,0,0,7.17-5.67,10.55-1.92,3.68,4.07,8.68.32,6.05-2.06A18.77,18.77,0,0,0,58.88,173.19Z\"></path><path class=\"cls-4\" d=\"M56.06,174.53c-3.86,2.57-3.86,8.62-3.86,8.62s7-3.81,6.5-6.19A2.93,2.93,0,0,0,56.06,174.53Z\"></path><path class=\"cls-4\" d=\"M24,127a5.49,5.49,0,0,1,4.43-.68l.2.08a14,14,0,0,0-.7-1.27c-3.49-6-7.76-4.79-11.56-2.21-.22.15-.43.31-.63.47a8.31,8.31,0,0,1,8.21,3.53Z\"></path><path class=\"cls-4\" d=\"M31.29,134.08c-2.48-9.82-4.47-13.62-14-6.83,0,0,8.13-2.34,9.06,9.22.44,5.47,5.69,6.57,5.63,3A18.77,18.77,0,0,0,31.29,134.08Z\"></path><path class=\"cls-4\" d=\"M27.83,128.82c-4.52-1.07-8.94,3.06-8.94,3.06s6.94-.24,7.78,4C27.14,138.23,27.83,128.82,27.83,128.82Z\"></path><path class=\"cls-22\" d=\"M172.45,112.79a55.39,55.39,0,0,1,15.49-12.5c5.64-3,13.66-4.84,18.5-4.61l1.85,1.59-1-.08a37.75,37.75,0,0,0-19,3.76A55,55,0,0,0,172.45,112.79Z\"></path><path class=\"cls-23\" d=\"M207.12,95.74a34.5,34.5,0,0,1,10.45,2.68,27.42,27.42,0,0,1,8.81,6,27.05,27.05,0,0,0-9.09-5.29,43.65,43.65,0,0,0-9-1.84l-1.84-1.59Z\"></path><path class=\"cls-24\" d=\"M124.52,175.47a27.43,27.43,0,0,1,3.11-1.9,25.35,25.35,0,0,1,2.31-1c.78-.34,1.58-.58,2.38-.84a45.63,45.63,0,0,1,9.84-1.81,95.67,95.67,0,0,1,19.84.78,194.33,194.33,0,0,0,19.66,1.89,66.25,66.25,0,0,0,19.6-1.93,66.44,66.44,0,0,1-19.6,2.3,194.82,194.82,0,0,1-19.75-1.52,94.77,94.77,0,0,0-19.65-.41,44.43,44.43,0,0,0-9.55,1.94c-.76.27-1.53.52-2.27.85a24,24,0,0,0-2.18,1,21.38,21.38,0,0,0-3.93,2.7l-.53.47A18.42,18.42,0,0,1,124.52,175.47Z\"></path><line class=\"cls-25\" x1=\"124.09\" y1=\"176.84\" x2=\"124.09\" y2=\"176.84\"></line><path class=\"cls-6\" d=\"M85.66,97.64c-6.36,1.4-5.37,6.45-5.37,6.45s2-2.43,13.09-3.74A52.36,52.36,0,0,1,85.66,97.64Z\"></path><path class=\"cls-26\" d=\"M118.59,191.58a16.4,16.4,0,0,1-.08-4.24,18.64,18.64,0,0,1,.91-4.18,18.86,18.86,0,0,1,1.87-3.9,19.81,19.81,0,0,1,2.78-3.38l.46-.42s-.63,2-.7,2.51a19.27,19.27,0,0,0-1.61,1.93,17.84,17.84,0,0,0-3.33,7.5A16.22,16.22,0,0,0,118.59,191.58Z\"></path><path class=\"cls-27\" d=\"M65.89,155.08c-3.61-4-6.65-10.29-7.95-16.2a36.79,36.79,0,0,1-.82-9.49l.14-2.38.33-2.36a23,23,0,0,1,.47-2.33,19.65,19.65,0,0,1,.6-2.3,35.6,35.6,0,0,1,3.83-8.64,39.45,39.45,0,0,1,2.68-3.89l1.53-1.8c.51-.6,1.1-1.13,1.64-1.69a37.2,37.2,0,0,1,7.47-5.68,39.82,39.82,0,0,1,8.62-3.62A39.67,39.67,0,0,0,76,98.56a36.78,36.78,0,0,0-7.22,5.83c-.52.57-1.08,1.11-1.56,1.71l-1.45,1.81a38.67,38.67,0,0,0-2.51,3.89,34.62,34.62,0,0,0-3.48,8.52,18.77,18.77,0,0,0-.52,2.24,21.9,21.9,0,0,0-.38,2.27l-.25,2.28-.06,2.3a35.25,35.25,0,0,0,1.06,9.07,36.17,36.17,0,0,0,8.62,15.83l.66.71S66.44,155.12,65.89,155.08Z\"></path><path class=\"cls-28\" d=\"M103.89,166.42A47.14,47.14,0,0,1,94,167.55,37.09,37.09,0,0,1,84,165.91,46.7,46.7,0,0,1,74.71,162a34.57,34.57,0,0,1-8.12-6.17l-.69-.74s2.38,0,3-.06a33.57,33.57,0,0,0,6.72,5.5,45.26,45.26,0,0,0,8.82,4.27A36.2,36.2,0,0,0,94,166.91,47.78,47.78,0,0,0,103.89,166.42Z\"></path></g></g></svg>"
 
 /***/ }),
 
-/***/ 81:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseIsNative = __webpack_require__(82),
-    getValue = __webpack_require__(88);
-
-/**
- * Gets the native function at `key` of `object`.
- *
- * @private
- * @param {Object} object The object to query.
- * @param {string} key The key of the method to get.
- * @returns {*} Returns the function if it's native, else `undefined`.
- */
-function getNative(object, key) {
-  var value = getValue(object, key);
-  return baseIsNative(value) ? value : undefined;
-}
-
-module.exports = getNative;
-
-
-/***/ }),
-
-/***/ 82:
-/***/ (function(module, exports, __webpack_require__) {
-
-var isFunction = __webpack_require__(83),
-    isMasked = __webpack_require__(85),
-    isObject = __webpack_require__(84),
-    toSource = __webpack_require__(87);
-
-/**
- * Used to match `RegExp`
- * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
- */
-var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
-
-/** Used to detect host constructors (Safari). */
-var reIsHostCtor = /^\[object .+?Constructor\]$/;
-
-/** Used for built-in method references. */
-var funcProto = Function.prototype,
-    objectProto = Object.prototype;
-
-/** Used to resolve the decompiled source of functions. */
-var funcToString = funcProto.toString;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/** Used to detect if a method is native. */
-var reIsNative = RegExp('^' +
-  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
-  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
-);
-
-/**
- * The base implementation of `_.isNative` without bad shim checks.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a native function,
- *  else `false`.
- */
-function baseIsNative(value) {
-  if (!isObject(value) || isMasked(value)) {
-    return false;
-  }
-  var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
-  return pattern.test(toSource(value));
-}
-
-module.exports = baseIsNative;
-
-
-/***/ }),
-
-/***/ 83:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseGetTag = __webpack_require__(6),
-    isObject = __webpack_require__(84);
-
-/** `Object#toString` result references. */
-var asyncTag = '[object AsyncFunction]',
-    funcTag = '[object Function]',
-    genTag = '[object GeneratorFunction]',
-    proxyTag = '[object Proxy]';
-
-/**
- * Checks if `value` is classified as a `Function` object.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a function, else `false`.
- * @example
- *
- * _.isFunction(_);
- * // => true
- *
- * _.isFunction(/abc/);
- * // => false
- */
-function isFunction(value) {
-  if (!isObject(value)) {
-    return false;
-  }
-  // The use of `Object#toString` avoids issues with the `typeof` operator
-  // in Safari 9 which returns 'object' for typed arrays and other constructors.
-  var tag = baseGetTag(value);
-  return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
-}
-
-module.exports = isFunction;
-
-
-/***/ }),
-
-/***/ 84:
-/***/ (function(module, exports) {
-
-/**
- * Checks if `value` is the
- * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
- * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an object, else `false`.
- * @example
- *
- * _.isObject({});
- * // => true
- *
- * _.isObject([1, 2, 3]);
- * // => true
- *
- * _.isObject(_.noop);
- * // => true
- *
- * _.isObject(null);
- * // => false
- */
-function isObject(value) {
-  var type = typeof value;
-  return value != null && (type == 'object' || type == 'function');
-}
-
-module.exports = isObject;
-
-
-/***/ }),
-
-/***/ 85:
-/***/ (function(module, exports, __webpack_require__) {
-
-var coreJsData = __webpack_require__(86);
-
-/** Used to detect methods masquerading as native. */
-var maskSrcKey = (function() {
-  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
-  return uid ? ('Symbol(src)_1.' + uid) : '';
-}());
-
-/**
- * Checks if `func` has its source masked.
- *
- * @private
- * @param {Function} func The function to check.
- * @returns {boolean} Returns `true` if `func` is masked, else `false`.
- */
-function isMasked(func) {
-  return !!maskSrcKey && (maskSrcKey in func);
-}
-
-module.exports = isMasked;
-
-
-/***/ }),
-
-/***/ 86:
-/***/ (function(module, exports, __webpack_require__) {
-
-var root = __webpack_require__(8);
-
-/** Used to detect overreaching core-js shims. */
-var coreJsData = root['__core-js_shared__'];
-
-module.exports = coreJsData;
-
-
-/***/ }),
-
-/***/ 87:
-/***/ (function(module, exports) {
-
-/** Used for built-in method references. */
-var funcProto = Function.prototype;
-
-/** Used to resolve the decompiled source of functions. */
-var funcToString = funcProto.toString;
-
-/**
- * Converts `func` to its source code.
- *
- * @private
- * @param {Function} func The function to convert.
- * @returns {string} Returns the source code.
- */
-function toSource(func) {
-  if (func != null) {
-    try {
-      return funcToString.call(func);
-    } catch (e) {}
-    try {
-      return (func + '');
-    } catch (e) {}
-  }
-  return '';
-}
-
-module.exports = toSource;
-
-
-/***/ }),
-
-/***/ 88:
-/***/ (function(module, exports) {
-
-/**
- * Gets the value at `key` of `object`.
- *
- * @private
- * @param {Object} [object] The object to query.
- * @param {string} key The key of the property to get.
- * @returns {*} Returns the property value.
- */
-function getValue(object, key) {
-  return object == null ? undefined : object[key];
-}
-
-module.exports = getValue;
-
-
-/***/ }),
-
-/***/ 89:
-/***/ (function(module, exports) {
-
-/**
- * Removes `key` and its value from the hash.
- *
- * @private
- * @name delete
- * @memberOf Hash
- * @param {Object} hash The hash to modify.
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function hashDelete(key) {
-  var result = this.has(key) && delete this.__data__[key];
-  this.size -= result ? 1 : 0;
-  return result;
-}
-
-module.exports = hashDelete;
-
-
-/***/ }),
-
-/***/ 9:
-/***/ (function(module, exports, __webpack_require__) {
-
-/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
-var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
-
-module.exports = freeGlobal;
-
-/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(792)))
-
-/***/ }),
-
-/***/ 90:
-/***/ (function(module, exports, __webpack_require__) {
-
-var nativeCreate = __webpack_require__(80);
-
-/** Used to stand-in for `undefined` hash values. */
-var HASH_UNDEFINED = '__lodash_hash_undefined__';
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Gets the hash value for `key`.
- *
- * @private
- * @name get
- * @memberOf Hash
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function hashGet(key) {
-  var data = this.__data__;
-  if (nativeCreate) {
-    var result = data[key];
-    return result === HASH_UNDEFINED ? undefined : result;
-  }
-  return hasOwnProperty.call(data, key) ? data[key] : undefined;
-}
-
-module.exports = hashGet;
-
-
-/***/ }),
-
-/***/ 91:
-/***/ (function(module, exports, __webpack_require__) {
-
-var nativeCreate = __webpack_require__(80);
-
-/** Used for built-in method references. */
-var objectProto = Object.prototype;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Checks if a hash value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf Hash
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function hashHas(key) {
-  var data = this.__data__;
-  return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
-}
-
-module.exports = hashHas;
-
-
-/***/ }),
-
 /***/ 919:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1792 1792\"><path d=\"M1395 1184q0 13-10 23l-50 50q-10 10-23 10t-23-10l-393-393-393 393q-10 10-23 10t-23-10l-50-50q-10-10-10-23t10-23l466-466q10-10 23-10t23 10l466 466q10 10 10 23z\" fill=\"#696969\"></path></svg>"
 
 /***/ }),
 
-/***/ 92:
-/***/ (function(module, exports, __webpack_require__) {
-
-var nativeCreate = __webpack_require__(80);
-
-/** Used to stand-in for `undefined` hash values. */
-var HASH_UNDEFINED = '__lodash_hash_undefined__';
-
-/**
- * Sets the hash `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf Hash
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the hash instance.
- */
-function hashSet(key, value) {
-  var data = this.__data__;
-  this.size += this.has(key) ? 0 : 1;
-  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
-  return this;
-}
-
-module.exports = hashSet;
-
-
-/***/ }),
-
 /***/ 920:
 /***/ (function(module, exports) {
 
 module.exports = "<!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1792 1792\"><path d=\"M1395 736q0 13-10 23l-466 466q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l393 393 393-393q10-10 23-10t23 10l50 50q10 10 10 23z\" fill=\"#696969\"></path></svg>"
 
 /***/ }),
 
-/***/ 93:
-/***/ (function(module, exports, __webpack_require__) {
-
-var listCacheClear = __webpack_require__(94),
-    listCacheDelete = __webpack_require__(95),
-    listCacheGet = __webpack_require__(98),
-    listCacheHas = __webpack_require__(99),
-    listCacheSet = __webpack_require__(100);
-
-/**
- * Creates an list cache object.
- *
- * @private
- * @constructor
- * @param {Array} [entries] The key-value pairs to cache.
- */
-function ListCache(entries) {
-  var index = -1,
-      length = entries == null ? 0 : entries.length;
-
-  this.clear();
-  while (++index < length) {
-    var entry = entries[index];
-    this.set(entry[0], entry[1]);
-  }
-}
-
-// Add methods to `ListCache`.
-ListCache.prototype.clear = listCacheClear;
-ListCache.prototype['delete'] = listCacheDelete;
-ListCache.prototype.get = listCacheGet;
-ListCache.prototype.has = listCacheHas;
-ListCache.prototype.set = listCacheSet;
-
-module.exports = ListCache;
-
-
-/***/ }),
-
-/***/ 94:
-/***/ (function(module, exports) {
-
-/**
- * Removes all key-value entries from the list cache.
- *
- * @private
- * @name clear
- * @memberOf ListCache
- */
-function listCacheClear() {
-  this.__data__ = [];
-  this.size = 0;
-}
-
-module.exports = listCacheClear;
-
-
-/***/ }),
-
-/***/ 95:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assocIndexOf = __webpack_require__(96);
-
-/** Used for built-in method references. */
-var arrayProto = Array.prototype;
-
-/** Built-in value references. */
-var splice = arrayProto.splice;
-
-/**
- * Removes `key` and its value from the list cache.
- *
- * @private
- * @name delete
- * @memberOf ListCache
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function listCacheDelete(key) {
-  var data = this.__data__,
-      index = assocIndexOf(data, key);
-
-  if (index < 0) {
-    return false;
-  }
-  var lastIndex = data.length - 1;
-  if (index == lastIndex) {
-    data.pop();
-  } else {
-    splice.call(data, index, 1);
-  }
-  --this.size;
-  return true;
-}
-
-module.exports = listCacheDelete;
-
-
-/***/ }),
-
-/***/ 96:
-/***/ (function(module, exports, __webpack_require__) {
-
-var eq = __webpack_require__(97);
-
-/**
- * Gets the index at which the `key` is found in `array` of key-value pairs.
- *
- * @private
- * @param {Array} array The array to inspect.
- * @param {*} key The key to search for.
- * @returns {number} Returns the index of the matched value, else `-1`.
- */
-function assocIndexOf(array, key) {
-  var length = array.length;
-  while (length--) {
-    if (eq(array[length][0], key)) {
-      return length;
-    }
-  }
-  return -1;
-}
-
-module.exports = assocIndexOf;
-
-
-/***/ }),
-
-/***/ 97:
-/***/ (function(module, exports) {
-
-/**
- * Performs a
- * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
- * comparison between two values to determine if they are equivalent.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- * @example
- *
- * var object = { 'a': 1 };
- * var other = { 'a': 1 };
- *
- * _.eq(object, object);
- * // => true
- *
- * _.eq(object, other);
- * // => false
- *
- * _.eq('a', 'a');
- * // => true
- *
- * _.eq('a', Object('a'));
- * // => false
- *
- * _.eq(NaN, NaN);
- * // => true
- */
-function eq(value, other) {
-  return value === other || (value !== value && other !== other);
-}
-
-module.exports = eq;
-
-
-/***/ }),
-
-/***/ 98:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assocIndexOf = __webpack_require__(96);
-
-/**
- * Gets the list cache value for `key`.
- *
- * @private
- * @name get
- * @memberOf ListCache
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function listCacheGet(key) {
-  var data = this.__data__,
-      index = assocIndexOf(data, key);
-
-  return index < 0 ? undefined : data[index][1];
-}
-
-module.exports = listCacheGet;
-
-
-/***/ }),
-
-/***/ 99:
-/***/ (function(module, exports, __webpack_require__) {
-
-var assocIndexOf = __webpack_require__(96);
-
-/**
- * Checks if a list cache value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf ListCache
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function listCacheHas(key) {
-  return assocIndexOf(this.__data__, key) > -1;
-}
-
-module.exports = listCacheHas;
-
-
-/***/ }),
-
 /***/ 993:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 exports.__esModule = true;
 exports.defaultMemoize = defaultMemoize;
--- a/devtools/client/debugger/new/src/actions/breakpoints.js
+++ b/devtools/client/debugger/new/src/actions/breakpoints.js
@@ -54,20 +54,26 @@ function _defineProperty(obj, key, value
  */
 function syncBreakpoint(sourceId, pendingBreakpoint) {
   return async ({
     dispatch,
     getState,
     client,
     sourceMaps
   }) => {
+    const response = await (0, _syncBreakpoint.syncClientBreakpoint)(getState, client, sourceMaps, sourceId, pendingBreakpoint);
+
+    if (!response) {
+      return;
+    }
+
     const {
       breakpoint,
       previousLocation
-    } = await (0, _syncBreakpoint.syncClientBreakpoint)(getState, client, sourceMaps, sourceId, pendingBreakpoint);
+    } = response;
     return dispatch({
       type: "SYNC_BREAKPOINT",
       breakpoint,
       previousLocation
     });
   };
 }
 /**
@@ -280,60 +286,51 @@ function toggleAllBreakpoints(shouldDisa
  * @static
  */
 
 
 function toggleBreakpoints(shouldDisableBreakpoints, breakpoints) {
   return async ({
     dispatch
   }) => {
-    for (const [, breakpoint] of breakpoints) {
-      if (shouldDisableBreakpoints) {
-        await dispatch(disableBreakpoint(breakpoint.location));
-      } else {
-        await dispatch(enableBreakpoint(breakpoint.location));
-      }
-    }
+    const promises = breakpoints.valueSeq().toJS().map(([, breakpoint]) => shouldDisableBreakpoints ? dispatch(disableBreakpoint(breakpoint.location)) : dispatch(enableBreakpoint(breakpoint.location)));
+    await Promise.all(promises);
   };
 }
 /**
  * Removes all breakpoints
  *
  * @memberof actions/breakpoints
  * @static
  */
 
 
 function removeAllBreakpoints() {
   return async ({
     dispatch,
     getState
   }) => {
-    const breakpoints = (0, _selectors.getBreakpoints)(getState());
-
-    for (const [, breakpoint] of breakpoints) {
-      await dispatch(removeBreakpoint(breakpoint.location));
-    }
+    const breakpointList = (0, _selectors.getBreakpoints)(getState()).valueSeq().toJS();
+    return Promise.all(breakpointList.map(bp => dispatch(removeBreakpoint(bp.location))));
   };
 }
 /**
  * Removes breakpoints
  *
  * @memberof actions/breakpoints
  * @static
  */
 
 
 function removeBreakpoints(breakpoints) {
   return async ({
     dispatch
   }) => {
-    for (const [, breakpoint] of breakpoints) {
-      await dispatch(removeBreakpoint(breakpoint.location));
-    }
+    const breakpointList = breakpoints.valueSeq().toJS();
+    return Promise.all(breakpointList.map(bp => dispatch(removeBreakpoint(bp.location))));
   };
 }
 
 function remapBreakpoints(sourceId) {
   return async ({
     dispatch,
     getState,
     sourceMaps
--- a/devtools/client/debugger/new/src/actions/breakpoints/syncBreakpoint.js
+++ b/devtools/client/debugger/new/src/actions/breakpoints/syncBreakpoint.js
@@ -51,19 +51,24 @@ function createSyncData(id, pendingBreak
     previousLocation
   };
 } // we have three forms of syncing: disabled syncing, existing server syncing
 // and adding a new breakpoint
 
 
 async function syncClientBreakpoint(getState, client, sourceMaps, sourceId, pendingBreakpoint) {
   (0, _breakpoint.assertPendingBreakpoint)(pendingBreakpoint);
-  const source = (0, _selectors.getSourceFromId)(getState(), sourceId);
+  const source = (0, _selectors.getSource)(getState(), sourceId);
   const generatedSourceId = sourceMaps.isOriginalId(sourceId) ? (0, _devtoolsSourceMap.originalToGeneratedId)(sourceId) : sourceId;
-  const generatedSource = (0, _selectors.getSourceFromId)(getState(), generatedSourceId);
+  const generatedSource = (0, _selectors.getSource)(getState(), generatedSourceId);
+
+  if (!source) {
+    return null;
+  }
+
   const {
     location,
     astLocation
   } = pendingBreakpoint;
 
   const previousLocation = _objectSpread({}, location, {
     sourceId
   });
--- a/devtools/client/debugger/new/src/actions/sources/newSources.js
+++ b/devtools/client/debugger/new/src/actions/sources/newSources.js
@@ -132,21 +132,18 @@ function checkPendingBreakpoints(sourceI
     const pendingBreakpoints = (0, _selectors.getPendingBreakpointsForSource)(getState(), source.url);
 
     if (!pendingBreakpoints.size) {
       return;
     } // load the source text if there is a pending breakpoint for it
 
 
     await dispatch((0, _loadSourceText.loadSourceText)(source));
-    const pendingBreakpointsArray = pendingBreakpoints.valueSeq().toJS();
-
-    for (const pendingBreakpoint of pendingBreakpointsArray) {
-      await dispatch((0, _breakpoints.syncBreakpoint)(sourceId, pendingBreakpoint));
-    }
+    const breakpoints = pendingBreakpoints.valueSeq().toJS();
+    await Promise.all(breakpoints.map(bp => dispatch((0, _breakpoints.syncBreakpoint)(sourceId, bp))));
   };
 }
 
 function restoreBlackBoxedSources(sources) {
   return async ({
     dispatch
   }) => {
     const tabs = (0, _selectors.getBlackBoxList)();
--- a/devtools/client/debugger/new/src/components/App.js
+++ b/devtools/client/debugger/new/src/components/App.js
@@ -289,9 +289,16 @@ const mapStateToProps = state => ({
   selectedSource: (0, _selectors.getSelectedSource)(state),
   startPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "start"),
   endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end"),
   activeSearch: (0, _selectors.getActiveSearch)(state),
   quickOpenEnabled: (0, _selectors.getQuickOpenEnabled)(state),
   orientation: (0, _selectors.getOrientation)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(App);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  setActiveSearch: _actions2.default.setActiveSearch,
+  closeActiveSearch: _actions2.default.closeActiveSearch,
+  closeProjectSearch: _actions2.default.closeProjectSearch,
+  openQuickOpen: _actions2.default.openQuickOpen,
+  closeQuickOpen: _actions2.default.closeQuickOpen,
+  setOrientation: _actions2.default.setOrientation
+})(App);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/Editor/Footer.js
+++ b/devtools/client/debugger/new/src/components/Editor/Footer.js
@@ -65,17 +65,17 @@ class SourceFooter extends _react.PureCo
 
   blackBoxButton() {
     const {
       selectedSource,
       toggleBlackBox
     } = this.props;
     const sourceLoaded = selectedSource && (0, _source.isLoaded)(selectedSource);
 
-    if (!sourceLoaded) {
+    if (!sourceLoaded || selectedSource.isPrettyPrinted) {
       return;
     }
 
     const blackboxed = selectedSource.isBlackBoxed;
     const tooltip = L10N.getStr("sourceFooter.blackbox");
     const type = "black-box";
     return _react2.default.createElement("button", {
       onClick: () => toggleBlackBox(selectedSource),
@@ -190,9 +190,15 @@ const mapStateToProps = state => {
   return {
     selectedSource,
     mappedSource: (0, _sources.getGeneratedSource)(state, selectedSource),
     prettySource: (0, _selectors.getPrettySource)(state, selectedId),
     endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end")
   };
 };
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SourceFooter);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  togglePrettyPrint: _actions2.default.togglePrettyPrint,
+  toggleBlackBox: _actions2.default.toggleBlackBox,
+  jumpToMappedLocation: _actions2.default.jumpToMappedLocation,
+  recordCoverage: _actions2.default.recordCoverage,
+  togglePaneCollapse: _actions2.default.togglePaneCollapse
+})(SourceFooter);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/Editor/Preview/index.js
+++ b/devtools/client/debugger/new/src/components/Editor/Preview/index.js
@@ -185,21 +185,14 @@ class Preview extends _react.PureCompone
 }
 
 const mapStateToProps = state => ({
   preview: (0, _selectors.getPreview)(state),
   isPaused: (0, _selectors.getIsPaused)(state),
   selectedSource: (0, _selectors.getSelectedSource)(state)
 });
 
-const {
-  addExpression,
-  setPopupObjectProperties,
-  updatePreview,
-  clearPreview
-} = _actions2.default;
-const mapDispatchToProps = {
-  addExpression,
-  setPopupObjectProperties,
-  updatePreview,
-  clearPreview
-};
-exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(Preview);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  clearPreview: _actions2.default.clearPreview,
+  setPopupObjectProperties: _actions2.default.setPopupObjectProperties,
+  addExpression: _actions2.default.addExpression,
+  updatePreview: _actions2.default.updatePreview
+})(Preview);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/Editor/SearchBar.js
+++ b/devtools/client/debugger/new/src/components/Editor/SearchBar.js
@@ -361,9 +361,17 @@ const mapStateToProps = state => ({
   selectedSource: (0, _selectors.getSelectedSource)(state),
   selectedLocation: (0, _selectors.getSelectedLocation)(state),
   query: (0, _selectors.getFileSearchQuery)(state),
   modifiers: (0, _selectors.getFileSearchModifiers)(state),
   highlightedLineRange: (0, _selectors.getHighlightedLineRange)(state),
   searchResults: (0, _selectors.getFileSearchResults)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SearchBar);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  toggleFileSearchModifier: _actions2.default.toggleFileSearchModifier,
+  setFileSearchQuery: _actions2.default.setFileSearchQuery,
+  setActiveSearch: _actions2.default.setActiveSearch,
+  closeFileSearch: _actions2.default.closeFileSearch,
+  doSearch: _actions2.default.doSearch,
+  traverseResults: _actions2.default.traverseResults,
+  updateSearchResults: _actions2.default.updateSearchResults
+})(SearchBar);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/Editor/Tab.js
+++ b/devtools/client/debugger/new/src/components/Editor/Tab.js
@@ -13,26 +13,22 @@ var _reactRedux = require("devtools/clie
 var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
 
 var _SourceIcon = require("../shared/SourceIcon");
 
 var _SourceIcon2 = _interopRequireDefault(_SourceIcon);
 
 var _Button = require("../shared/Button/index");
 
-var _text = require("../../utils/text");
-
 var _actions = require("../../actions/index");
 
 var _actions2 = _interopRequireDefault(_actions);
 
 var _source = require("../../utils/source");
 
-var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"];
-
 var _clipboard = require("../../utils/clipboard");
 
 var _tabs = require("../../utils/tabs");
 
 var _selectors = require("../../selectors/index");
 
 var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
 
@@ -136,17 +132,16 @@ class Tab extends _react.PureComponent {
 
   render() {
     const {
       selectedSource,
       selectSpecificSource,
       closeTab,
       source
     } = this.props;
-    const filename = (0, _source.getFilename)(source);
     const sourceId = source.id;
     const active = selectedSource && sourceId == selectedSource.id && !this.isProjectSearchEnabled() && !this.isSourceSearchEnabled();
     const isPrettyCode = (0, _source.isPretty)(source);
 
     function onClickClose(e) {
       e.stopPropagation();
       closeTab(source.url);
     }
@@ -172,17 +167,17 @@ class Tab extends _react.PureComponent {
       onMouseUp: handleTabClick,
       onContextMenu: e => this.onTabContextMenu(e, sourceId),
       title: (0, _source.getFileURL)(source)
     }, _react2.default.createElement(_SourceIcon2.default, {
       source: source,
       shouldHide: icon => ["file", "javascript"].includes(icon)
     }), _react2.default.createElement("div", {
       className: "filename"
-    }, (0, _text.truncateMiddleText)((0, _devtoolsModules.getUnicodeUrlPath)(filename), 30)), _react2.default.createElement(_Button.CloseButton, {
+    }, (0, _source.getTruncatedFileName)(source)), _react2.default.createElement(_Button.CloseButton, {
       handleClick: onClickClose,
       tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip")
     }));
   }
 
 }
 
 const mapStateToProps = (state, {
@@ -191,9 +186,15 @@ const mapStateToProps = (state, {
   const selectedSource = (0, _selectors.getSelectedSource)(state);
   return {
     tabSources: (0, _selectors.getSourcesForTabs)(state),
     selectedSource: selectedSource,
     activeSearch: (0, _selectors.getActiveSearch)(state)
   };
 };
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Tab);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  selectSpecificSource: _actions2.default.selectSpecificSource,
+  closeTab: _actions2.default.closeTab,
+  closeTabs: _actions2.default.closeTabs,
+  togglePrettyPrint: _actions2.default.togglePrettyPrint,
+  showSource: _actions2.default.showSource
+})(Tab);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/Editor/Tabs.js
+++ b/devtools/client/debugger/new/src/components/Editor/Tabs.js
@@ -51,17 +51,17 @@ class Tabs extends _react.PureComponent 
       const {
         selectedSource,
         tabSources,
         moveTab
       } = this.props;
       const sourceTabEls = this.refs.sourceTabs.children;
       const hiddenTabs = (0, _tabs.getHiddenTabs)(tabSources, sourceTabEls);
 
-      if ((0, _ui.isVisible)() && hiddenTabs.find(tab => tab.id == selectedSource.id)) {
+      if (selectedSource && (0, _ui.isVisible)() && hiddenTabs.find(tab => tab.id == selectedSource.id)) {
         return moveTab(selectedSource.url, 0);
       }
 
       this.setState({
         hiddenTabs
       });
     };
 
@@ -200,9 +200,15 @@ class Tabs extends _react.PureComponent 
 
 }
 
 const mapStateToProps = state => ({
   selectedSource: (0, _selectors.getSelectedSource)(state),
   tabSources: (0, _selectors.getSourcesForTabs)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Tabs);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  selectSpecificSource: _actions2.default.selectSpecificSource,
+  moveTab: _actions2.default.moveTab,
+  closeTab: _actions2.default.closeTab,
+  togglePaneCollapse: _actions2.default.togglePaneCollapse,
+  showSource: _actions2.default.showSource
+})(Tabs);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/Editor/index.js
+++ b/devtools/client/debugger/new/src/components/Editor/index.js
@@ -630,9 +630,18 @@ const mapStateToProps = state => {
     searchOn: (0, _selectors.getActiveSearch)(state) === "file",
     hitCount: (0, _selectors.getHitCountForSource)(state, sourceId),
     coverageOn: (0, _selectors.getCoverageEnabled)(state),
     conditionalPanelLine: (0, _selectors.getConditionalPanelLine)(state),
     symbols: (0, _selectors.getSymbols)(state, selectedSource)
   };
 };
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Editor);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  openConditionalPanel: _actions2.default.openConditionalPanel,
+  closeConditionalPanel: _actions2.default.closeConditionalPanel,
+  setContextMenu: _actions2.default.setContextMenu,
+  continueToHere: _actions2.default.continueToHere,
+  toggleBreakpoint: _actions2.default.toggleBreakpoint,
+  addOrToggleDisabledBreakpoint: _actions2.default.addOrToggleDisabledBreakpoint,
+  jumpToMappedLocation: _actions2.default.jumpToMappedLocation,
+  traverseResults: _actions2.default.traverseResults
+})(Editor);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js
@@ -197,9 +197,13 @@ const mapStateToProps = state => {
   return {
     symbols,
     selectedSource,
     selectedLocation: (0, _selectors.getSelectedLocation)(state),
     getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource, symbols)
   };
 };
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Outline);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  selectLocation: _actions2.default.selectLocation,
+  getFunctionText: _actions2.default.getFunctionText,
+  flashLineRange: _actions2.default.flashLineRange
+})(Outline);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
@@ -7,48 +7,40 @@ Object.defineProperty(exports, "__esModu
 var _react = require("devtools/client/shared/vendor/react");
 
 var _react2 = _interopRequireDefault(_react);
 
 var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
 
 var _classnames2 = _interopRequireDefault(_classnames);
 
-var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
-
 var _reactRedux = require("devtools/client/shared/vendor/react-redux");
 
-var _SourceIcon = require("../shared/SourceIcon");
-
-var _SourceIcon2 = _interopRequireDefault(_SourceIcon);
-
 var _selectors = require("../../selectors/index");
 
-var _sourceTree = require("../../actions/source-tree");
+var _actions = require("../../actions/index");
+
+var _actions2 = _interopRequireDefault(_actions);
 
-var _sources = require("../../actions/sources/index");
+var _source = require("../../utils/source");
 
-var _ui = require("../../actions/ui");
+var _SourcesTreeItem = require("./SourcesTreeItem");
+
+var _SourcesTreeItem2 = _interopRequireDefault(_SourcesTreeItem);
 
 var _ManagedTree = require("../shared/ManagedTree");
 
 var _ManagedTree2 = _interopRequireDefault(_ManagedTree);
 
 var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"];
 
 var _Svg2 = _interopRequireDefault(_Svg);
 
 var _sourcesTree = require("../../utils/sources-tree/index");
 
-var _source = require("../../utils/source");
-
-var _clipboard = require("../../utils/clipboard");
-
-var _prefs = require("../../utils/prefs");
-
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 // Dependencies
 // Selectors
 // Actions
@@ -91,29 +83,35 @@ class SourcesTree extends _react.Compone
       return this.setState((0, _sourcesTree.createTree)({
         sources: nextProps.sources,
         debuggeeUrl: nextProps.debuggeeUrl,
         projectRoot: nextProps.projectRoot
       }));
     }
 
     if (nextProps.shownSource && nextProps.shownSource != shownSource) {
-      const listItems = (0, _sourcesTree.getDirectories)(nextProps.shownSource, sourceTree);
+      const matchingSources = Object.keys(sources).filter(sourceId => {
+        return (0, _source.getRawSourceURL)(sources[sourceId].url) === nextProps.shownSource;
+      });
+
+      if (matchingSources.length) {
+        const listItems = (0, _sourcesTree.getDirectories)(sources[matchingSources[0]], sourceTree);
 
-      if (listItems && listItems[0]) {
-        this.selectItem(listItems[0]);
+        if (listItems && listItems.length) {
+          this.selectItem(listItems[0]);
+        }
+
+        return this.setState({
+          listItems
+        });
       }
-
-      return this.setState({
-        listItems
-      });
     }
 
     if (nextProps.selectedSource && nextProps.selectedSource != selectedSource) {
-      const highlightItems = (0, _sourcesTree.getDirectories)((0, _source.getRawSourceURL)(nextProps.selectedSource.url), sourceTree);
+      const highlightItems = (0, _sourcesTree.getDirectories)(nextProps.selectedSource, sourceTree);
       this.setState({
         highlightItems
       });
     } // NOTE: do not run this every time a source is clicked,
     // only when a new source is added
 
 
     if (nextProps.sources != this.props.sources) {
@@ -141,32 +139,16 @@ class SourcesTree extends _react.Compone
 
   isEmpty() {
     const {
       sourceTree
     } = this.state;
     return sourceTree.contents.length === 0;
   }
 
-  renderItemName(name) {
-    switch (name) {
-      case "ng://":
-        return "Angular";
-
-      case "webpack://":
-        return "Webpack";
-
-      case "moz-extension://":
-        return L10N.getStr("extensionsText");
-
-      default:
-        return name;
-    }
-  }
-
   renderEmptyElement(message) {
     return _react2.default.createElement("div", {
       key: "empty",
       className: "no-sources-message"
     }, message);
   }
 
   renderProjectRootHeader() {
@@ -278,120 +260,21 @@ var _initialiseProps = function () {
   this.getPath = item => {
     const path = `${item.path}/${item.name}`;
 
     if ((0, _sourcesTree.isDirectory)(item)) {
       return path;
     }
 
     const source = this.getSource(item);
-    const blackBoxedPart = source && source.isBlackBoxed ? ":blackboxed" : "";
-    return `${path}${blackBoxedPart}`;
-  };
-
-  this.getIcon = (sources, item, depth) => {
-    const {
-      debuggeeUrl,
-      projectRoot
-    } = this.props;
-
-    if (item.path === "webpack://") {
-      return _react2.default.createElement(_Svg2.default, {
-        name: "webpack"
-      });
-    } else if (item.path === "ng://") {
-      return _react2.default.createElement(_Svg2.default, {
-        name: "angular"
-      });
-    } else if (item.path === "moz-extension://") {
-      return _react2.default.createElement("img", {
-        className: "extension"
-      });
-    }
-
-    if (depth === 0 && projectRoot === "") {
-      return _react2.default.createElement("img", {
-        className: (0, _classnames2.default)("domain", {
-          debuggee: debuggeeUrl && debuggeeUrl.includes(item.name)
-        })
-      });
-    }
-
-    if ((0, _sourcesTree.isDirectory)(item)) {
-      return _react2.default.createElement("img", {
-        className: "folder"
-      });
-    }
-
-    const source = this.getSource(item);
-
-    if (source) {
-      return _react2.default.createElement(_SourceIcon2.default, {
-        source: source
-      });
-    }
-
-    return null;
-  };
+    const blackBoxedPart = source && source.isBlackBoxed ? ":blackboxed" : ""; // Original and generated sources can point to the same path
+    // therefore necessary to distinguish as path is used as keys.
 
-  this.onContextMenu = (event, item) => {
-    const copySourceUri2Label = L10N.getStr("copySourceUri2");
-    const copySourceUri2Key = L10N.getStr("copySourceUri2.accesskey");
-    const setDirectoryRootLabel = L10N.getStr("setDirectoryRoot.label");
-    const setDirectoryRootKey = L10N.getStr("setDirectoryRoot.accesskey");
-    const removeDirectoryRootLabel = L10N.getStr("removeDirectoryRoot.label");
-    event.stopPropagation();
-    event.preventDefault();
-    const menuOptions = [];
-
-    if (!(0, _sourcesTree.isDirectory)(item)) {
-      // Flow requires some extra handling to ensure the value of contents.
-      const {
-        contents
-      } = item;
-
-      if (!Array.isArray(contents)) {
-        const copySourceUri2 = {
-          id: "node-menu-copy-source",
-          label: copySourceUri2Label,
-          accesskey: copySourceUri2Key,
-          disabled: false,
-          click: () => (0, _clipboard.copyToTheClipboard)(contents.url)
-        };
-        menuOptions.push(copySourceUri2);
-      }
-    }
-
-    if ((0, _sourcesTree.isDirectory)(item) && _prefs.features.root) {
-      const {
-        path
-      } = item;
-      const {
-        projectRoot
-      } = this.props;
-
-      if (projectRoot.endsWith(path)) {
-        menuOptions.push({
-          id: "node-remove-directory-root",
-          label: removeDirectoryRootLabel,
-          disabled: false,
-          click: () => this.props.clearProjectDirectoryRoot()
-        });
-      } else {
-        menuOptions.push({
-          id: "node-set-directory-root",
-          label: setDirectoryRootLabel,
-          accesskey: setDirectoryRootKey,
-          disabled: false,
-          click: () => this.props.setProjectDirectoryRoot(path)
-        });
-      }
-    }
-
-    (0, _devtoolsContextmenu.showMenu)(event, menuOptions);
+    const generatedPart = source && source.sourceMapURL ? ":generated" : "";
+    return `${path}${blackBoxedPart}${generatedPart}`;
   };
 
   this.onExpand = (item, expandedState) => {
     this.props.setExpandedState(expandedState);
   };
 
   this.onCollapse = (item, expandedState) => {
     this.props.setExpandedState(expandedState);
@@ -402,50 +285,16 @@ var _initialiseProps = function () {
       focusedItem
     } = this.state;
 
     if (e.keyCode === 13 && focusedItem) {
       this.selectItem(focusedItem);
     }
   };
 
-  this.renderItem = (item, depth, focused, _, expanded, {
-    setExpanded
-  }) => {
-    const arrow = (0, _sourcesTree.isDirectory)(item) ? _react2.default.createElement("img", {
-      className: (0, _classnames2.default)("arrow", {
-        expanded: expanded
-      })
-    }) : _react2.default.createElement("i", {
-      className: "no-arrow"
-    });
-    const {
-      sources
-    } = this.props;
-    const icon = this.getIcon(sources, item, depth);
-    return _react2.default.createElement("div", {
-      className: (0, _classnames2.default)("node", {
-        focused
-      }),
-      key: item.path,
-      onClick: e => {
-        this.focusItem(item);
-
-        if ((0, _sourcesTree.isDirectory)(item)) {
-          setExpanded(item, !!expanded, e.altKey);
-        } else {
-          this.selectItem(item);
-        }
-      },
-      onContextMenu: e => this.onContextMenu(e, item)
-    }, arrow, icon, _react2.default.createElement("span", {
-      className: "label"
-    }, " ", this.renderItemName(item.name), " "));
-  };
-
   this.getRoots = () => {
     const {
       projectRoot
     } = this.props;
     const {
       sourceTree
     } = this.state;
     const sourceContents = sourceTree.contents[0];
@@ -457,29 +306,51 @@ var _initialiseProps = function () {
         return sourceContents.contents[0].contents;
       }
 
       return sourceContents.contents;
     }
 
     return sourceTree.contents;
   };
+
+  this.renderItem = (item, depth, focused, _, expanded, {
+    setExpanded
+  }) => {
+    const {
+      debuggeeUrl,
+      projectRoot
+    } = this.props;
+    return _react2.default.createElement(_SourcesTreeItem2.default, {
+      item: item,
+      depth: depth,
+      focused: focused,
+      expanded: expanded,
+      setExpanded: setExpanded,
+      focusItem: this.focusItem,
+      selectItem: this.selectItem,
+      source: this.getSource(item),
+      debuggeeUrl: debuggeeUrl,
+      projectRoot: projectRoot,
+      clearProjectDirectoryRoot: this.props.clearProjectDirectoryRoot,
+      setProjectDirectoryRoot: this.props.setProjectDirectoryRoot
+    });
+  };
 };
 
 const mapStateToProps = state => {
   return {
     shownSource: (0, _selectors.getShownSource)(state),
     selectedSource: (0, _selectors.getSelectedSource)(state),
     debuggeeUrl: (0, _selectors.getDebuggeeUrl)(state),
     expanded: (0, _selectors.getExpandedState)(state),
     projectRoot: (0, _selectors.getProjectDirectoryRoot)(state),
     sources: (0, _selectors.getRelativeSources)(state),
     sourceCount: (0, _selectors.getSourceCount)(state)
   };
 };
 
-const actionCreators = {
-  setExpandedState: _sourceTree.setExpandedState,
-  selectSource: _sources.selectSource,
-  setProjectDirectoryRoot: _ui.setProjectDirectoryRoot,
-  clearProjectDirectoryRoot: _ui.clearProjectDirectoryRoot
-};
-exports.default = (0, _reactRedux.connect)(mapStateToProps, actionCreators)(SourcesTree);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  selectSource: _actions2.default.selectSource,
+  setExpandedState: _actions2.default.setExpandedState,
+  setProjectDirectoryRoot: _actions2.default.setProjectDirectoryRoot,
+  clearProjectDirectoryRoot: _actions2.default.clearProjectDirectoryRoot
+})(SourcesTree);
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTreeItem.js
@@ -0,0 +1,207 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _react = require("devtools/client/shared/vendor/react");
+
+var _react2 = _interopRequireDefault(_react);
+
+var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
+
+var _classnames2 = _interopRequireDefault(_classnames);
+
+var _devtoolsContextmenu = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-contextmenu"];
+
+var _SourceIcon = require("../shared/SourceIcon");
+
+var _SourceIcon2 = _interopRequireDefault(_SourceIcon);
+
+var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"];
+
+var _Svg2 = _interopRequireDefault(_Svg);
+
+var _sourcesTree = require("../../utils/sources-tree/index");
+
+var _clipboard = require("../../utils/clipboard");
+
+var _prefs = require("../../utils/prefs");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
+class SourceTreeItem extends _react.Component {
+  constructor(...args) {
+    var _temp;
+
+    return _temp = super(...args), this.onClick = e => {
+      const {
+        expanded,
+        item,
+        focusItem,
+        setExpanded,
+        selectItem
+      } = this.props;
+      focusItem(item);
+
+      if ((0, _sourcesTree.isDirectory)(item)) {
+        setExpanded(item, !!expanded, e.altKey);
+      } else {
+        selectItem(item);
+      }
+    }, this.onContextMenu = (event, item) => {
+      const copySourceUri2Label = L10N.getStr("copySourceUri2");
+      const copySourceUri2Key = L10N.getStr("copySourceUri2.accesskey");
+      const setDirectoryRootLabel = L10N.getStr("setDirectoryRoot.label");
+      const setDirectoryRootKey = L10N.getStr("setDirectoryRoot.accesskey");
+      const removeDirectoryRootLabel = L10N.getStr("removeDirectoryRoot.label");
+      event.stopPropagation();
+      event.preventDefault();
+      const menuOptions = [];
+
+      if (!(0, _sourcesTree.isDirectory)(item)) {
+        // Flow requires some extra handling to ensure the value of contents.
+        const {
+          contents
+        } = item;
+
+        if (!Array.isArray(contents)) {
+          const copySourceUri2 = {
+            id: "node-menu-copy-source",
+            label: copySourceUri2Label,
+            accesskey: copySourceUri2Key,
+            disabled: false,
+            click: () => (0, _clipboard.copyToTheClipboard)(contents.url)
+          };
+          menuOptions.push(copySourceUri2);
+        }
+      }
+
+      if ((0, _sourcesTree.isDirectory)(item) && _prefs.features.root) {
+        const {
+          path
+        } = item;
+        const {
+          projectRoot
+        } = this.props;
+
+        if (projectRoot.endsWith(path)) {
+          menuOptions.push({
+            id: "node-remove-directory-root",
+            label: removeDirectoryRootLabel,
+            disabled: false,
+            click: () => this.props.clearProjectDirectoryRoot()
+          });
+        } else {
+          menuOptions.push({
+            id: "node-set-directory-root",
+            label: setDirectoryRootLabel,
+            accesskey: setDirectoryRootKey,
+            disabled: false,
+            click: () => this.props.setProjectDirectoryRoot(path)
+          });
+        }
+      }
+
+      (0, _devtoolsContextmenu.showMenu)(event, menuOptions);
+    }, _temp;
+  }
+
+  getIcon(item, depth) {
+    const {
+      debuggeeUrl,
+      projectRoot,
+      source
+    } = this.props;
+
+    if (item.path === "webpack://") {
+      return _react2.default.createElement(_Svg2.default, {
+        name: "webpack"
+      });
+    } else if (item.path === "ng://") {
+      return _react2.default.createElement(_Svg2.default, {
+        name: "angular"
+      });
+    } else if (item.path === "moz-extension://") {
+      return _react2.default.createElement("img", {
+        className: "extension"
+      });
+    }
+
+    if (depth === 0 && projectRoot === "") {
+      return _react2.default.createElement("img", {
+        className: (0, _classnames2.default)("domain", {
+          debuggee: debuggeeUrl && debuggeeUrl.includes(item.name)
+        })
+      });
+    }
+
+    if ((0, _sourcesTree.isDirectory)(item)) {
+      return _react2.default.createElement("img", {
+        className: "folder"
+      });
+    }
+
+    if (source) {
+      return _react2.default.createElement(_SourceIcon2.default, {
+        source: source
+      });
+    }
+
+    return null;
+  }
+
+  renderItemArrow() {
+    const {
+      item,
+      expanded
+    } = this.props;
+    return (0, _sourcesTree.isDirectory)(item) ? _react2.default.createElement("img", {
+      className: (0, _classnames2.default)("arrow", {
+        expanded
+      })
+    }) : _react2.default.createElement("i", {
+      className: "no-arrow"
+    });
+  }
+
+  renderItemName(name) {
+    switch (name) {
+      case "ng://":
+        return "Angular";
+
+      case "webpack://":
+        return "Webpack";
+
+      case "moz-extension://":
+        return L10N.getStr("extensionsText");
+
+      default:
+        return name;
+    }
+  }
+
+  render() {
+    const {
+      item,
+      depth,
+      focused
+    } = this.props;
+    return _react2.default.createElement("div", {
+      className: (0, _classnames2.default)("node", {
+        focused
+      }),
+      key: item.path,
+      onClick: this.onClick,
+      onContextMenu: e => this.onContextMenu(e, item)
+    }, this.renderItemArrow(), this.getIcon(item, depth), _react2.default.createElement("span", {
+      className: "label"
+    }, " ", this.renderItemName(item.name), " "));
+  }
+
+}
+
+exports.default = SourceTreeItem;
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/index.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/index.js
@@ -119,9 +119,14 @@ class PrimaryPanes extends _react.Compon
 }
 
 const mapStateToProps = state => ({
   selectedTab: (0, _selectors.getSelectedPrimaryPaneTab)(state),
   sources: (0, _selectors.getSources)(state),
   sourceSearchOn: (0, _selectors.getActiveSearch)(state) === "source"
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(PrimaryPanes);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  setPrimaryPaneTab: _actions2.default.setPrimaryPaneTab,
+  selectLocation: _actions2.default.selectLocation,
+  setActiveSearch: _actions2.default.setActiveSearch,
+  closeActiveSearch: _actions2.default.closeActiveSearch
+})(PrimaryPanes);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/moz.build
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/moz.build
@@ -6,9 +6,10 @@
 DIRS += [
 
 ]
 
 DevToolsModules(
     'index.js',
     'Outline.js',
     'SourcesTree.js',
+    'SourcesTreeItem.js',
 )
--- a/devtools/client/debugger/new/src/components/ProjectSearch.js
+++ b/devtools/client/debugger/new/src/components/ProjectSearch.js
@@ -316,9 +316,16 @@ ProjectSearch.contextTypes = {
 const mapStateToProps = state => ({
   sources: (0, _selectors.getSources)(state),
   activeSearch: (0, _selectors.getActiveSearch)(state),
   results: (0, _selectors.getTextSearchResults)(state),
   query: (0, _selectors.getTextSearchQuery)(state),
   status: (0, _selectors.getTextSearchStatus)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(ProjectSearch);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  closeProjectSearch: _actions2.default.closeProjectSearch,
+  searchSources: _actions2.default.searchSources,
+  clearSearch: _actions2.default.clearSearch,
+  selectLocation: _actions2.default.selectLocation,
+  setActiveSearch: _actions2.default.setActiveSearch,
+  doSearchForHighlight: _actions2.default.doSearchForHighlight
+})(ProjectSearch);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/QuickOpenModal.js
+++ b/devtools/client/debugger/new/src/components/QuickOpenModal.js
@@ -479,9 +479,16 @@ function mapStateToProps(state) {
     query: (0, _selectors.getQuickOpenQuery)(state),
     searchType: (0, _selectors.getQuickOpenType)(state),
     tabs: (0, _selectors.getTabs)(state)
   };
 }
 /* istanbul ignore next: ignoring testing of redux connection stuff */
 
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(QuickOpenModal);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  shortcutsModalEnabled: _actions2.default.shortcutsModalEnabled,
+  selectLocation: _actions2.default.selectLocation,
+  setQuickOpenQuery: _actions2.default.setQuickOpenQuery,
+  highlightLineRange: _actions2.default.highlightLineRange,
+  closeQuickOpen: _actions2.default.closeQuickOpen,
+  toggleShortcutsModal: _actions2.default.toggleShortcutsModal
+})(QuickOpenModal);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js
@@ -191,9 +191,20 @@ class Breakpoint extends _react.PureComp
 }
 
 const mapStateToProps = state => ({
   breakpoints: (0, _selectors.getBreakpoints)(state),
   frame: (0, _selectors.getTopFrame)(state),
   selectedSource: (0, _selectors.getSelectedSource)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoint);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  enableBreakpoint: _actions2.default.enableBreakpoint,
+  removeBreakpoint: _actions2.default.removeBreakpoint,
+  removeBreakpoints: _actions2.default.removeBreakpoints,
+  removeAllBreakpoints: _actions2.default.removeAllBreakpoints,
+  disableBreakpoint: _actions2.default.disableBreakpoint,
+  selectSpecificLocation: _actions2.default.selectSpecificLocation,
+  selectLocation: _actions2.default.selectLocation,
+  toggleAllBreakpoints: _actions2.default.toggleAllBreakpoints,
+  toggleBreakpoints: _actions2.default.toggleBreakpoints,
+  openConditionalPanel: _actions2.default.openConditionalPanel
+})(Breakpoint);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/BreakpointsContextMenu.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/BreakpointsContextMenu.js
@@ -13,17 +13,17 @@ var _devtoolsContextmenu = require("devt
 function showContextMenu(props) {
   const {
     removeBreakpoint,
     removeBreakpoints,
     removeAllBreakpoints,
     toggleBreakpoints,
     toggleAllBreakpoints,
     toggleDisabledBreakpoint,
-    selectLocation,
+    selectSpecificLocation,
     setBreakpointCondition,
     openConditionalPanel,
     breakpoints,
     breakpoint,
     contextMenuEvent
   } = props;
   contextMenuEvent.preventDefault();
   const deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf2.label");
@@ -124,26 +124,26 @@ function showContextMenu(props) {
     disabled: false,
     click: () => setBreakpointCondition(breakpoint.location)
   };
   const addConditionItem = {
     id: "node-menu-add-condition",
     label: addConditionLabel,
     accesskey: addConditionKey,
     click: () => {
-      selectLocation(breakpoint.location);
+      selectSpecificLocation(breakpoint.location);
       openConditionalPanel(breakpoint.location.line);
     }
   };
   const editConditionItem = {
     id: "node-menu-edit-condition",
     label: editConditionLabel,
     accesskey: editConditionKey,
     click: () => {
-      selectLocation(breakpoint.location);
+      selectSpecificLocation(breakpoint.location);
       openConditionalPanel(breakpoint.location.line);
     }
   };
   const hideEnableSelfItem = !breakpoint.disabled;
   const hideEnableAllItem = disabledBreakpoints.size === 0;
   const hideEnableOthersItem = otherDisabledBreakpoints.size === 0;
   const hideDisableAllItem = enabledBreakpoints.size === 0;
   const hideDisableOthersItem = otherEnabledBreakpoints.size === 0;
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/index.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/index.js
@@ -78,17 +78,17 @@ class Breakpoints extends _react.Compone
     }) => [_react2.default.createElement("div", {
       className: "breakpoint-heading",
       title: (0, _source.getRawSourceURL)(source.url),
       key: source.url,
       onClick: () => this.props.selectSource(source.id)
     }, _react2.default.createElement(_SourceIcon2.default, {
       source: source,
       shouldHide: icon => ["file", "javascript"].includes(icon)
-    }), (0, _source.getFilename)(source)), ...breakpoints.map(breakpoint => _react2.default.createElement(_Breakpoint2.default, {
+    }), (0, _source.getTruncatedFileName)(source)), ...breakpoints.map(breakpoint => _react2.default.createElement(_Breakpoint2.default, {
       breakpoint: breakpoint,
       source: source,
       key: (0, _breakpoint.makeLocationId)(breakpoint.location)
     }))])];
   }
 
   render() {
     return _react2.default.createElement("div", {
@@ -98,9 +98,12 @@ class Breakpoints extends _react.Compone
 
 }
 
 const mapStateToProps = state => ({
   breakpointSources: (0, _selectors.getBreakpointSources)(state),
   selectedSource: (0, _selectors.getSelectedSource)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoints);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  pauseOnExceptions: _actions2.default.pauseOnExceptions,
+  selectSource: _actions2.default.selectSource
+})(Breakpoints);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.js
@@ -288,9 +288,23 @@ const mapStateToProps = state => ({
   isPaused: (0, _selectors.isPaused)(state),
   history: (0, _selectors.getHistory)(state),
   historyPosition: (0, _selectors.getHistoryPosition)(state),
   isWaitingOnBreak: (0, _selectors.getIsWaitingOnBreak)(state),
   canRewind: (0, _selectors.getCanRewind)(state),
   skipPausing: (0, _selectors.getSkipPausing)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(CommandBar);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  timeTravelTo: _actions2.default.timeTravelTo,
+  clearHistory: _actions2.default.clearHistory,
+  resume: _actions2.default.resume,
+  stepIn: _actions2.default.stepIn,
+  stepOut: _actions2.default.stepOut,
+  stepOver: _actions2.default.stepOver,
+  breakOnNext: _actions2.default.breakOnNext,
+  rewind: _actions2.default.rewind,
+  reverseStepIn: _actions2.default.reverseStepIn,
+  reverseStepOut: _actions2.default.reverseStepOut,
+  reverseStepOver: _actions2.default.reverseStepOver,
+  pauseOnExceptions: _actions2.default.pauseOnExceptions,
+  toggleSkipPausing: _actions2.default.toggleSkipPausing
+})(CommandBar);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.js
@@ -106,9 +106,15 @@ const mapStateToProps = state => {
       })
     });
   });
   return {
     listeners
   };
 };
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(EventListeners);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  selectLocation: _actions2.default.selectLocation,
+  addBreakpoint: _actions2.default.addBreakpoint,
+  enableBreakpoint: _actions2.default.enableBreakpoint,
+  disableBreakpoint: _actions2.default.disableBreakpoint,
+  removeBreakpoint: _actions2.default.removeBreakpoint
+})(EventListeners);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.js
@@ -368,9 +368,19 @@ class Expressions extends _react.Compone
 const mapStateToProps = state => {
   return {
     autocompleteMatches: (0, _selectors.getAutocompleteMatchset)(state),
     expressions: (0, _selectors.getExpressions)(state),
     expressionError: (0, _selectors.getExpressionError)(state)
   };
 };
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Expressions);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  autocomplete: _actions2.default.autocomplete,
+  clearAutocomplete: _actions2.default.clearAutocomplete,
+  onExpressionAdded: _actions2.default.onExpressionAdded,
+  addExpression: _actions2.default.addExpression,
+  clearExpressionError: _actions2.default.clearExpressionError,
+  evaluateExpressions: _actions2.default.evaluateExpressions,
+  updateExpression: _actions2.default.updateExpression,
+  deleteExpression: _actions2.default.deleteExpression,
+  openLink: _actions2.default.openLink
+})(Expressions);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/index.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/index.js
@@ -169,9 +169,14 @@ class Frames extends _react.Component {
 const mapStateToProps = state => ({
   frames: (0, _selectors.getCallStackFrames)(state),
   why: (0, _selectors.getPauseReason)(state),
   frameworkGroupingOn: (0, _selectors.getFrameworkGroupingState)(state),
   selectedFrame: (0, _selectors.getSelectedFrame)(state),
   pause: (0, _selectors.isPaused)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Frames);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  selectFrame: _actions2.default.selectFrame,
+  toggleBlackBox: _actions2.default.toggleBlackBox,
+  toggleFrameworkGrouping: _actions2.default.toggleFrameworkGrouping,
+  disableFrameTruncate: _actions2.default.disableFrameTruncate
+})(Frames);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/FrameworkComponent.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/FrameworkComponent.js
@@ -108,9 +108,11 @@ class FrameworkComponent extends _react.
 
 }
 
 const mapStateToProps = state => ({
   selectedFrame: (0, _selectors.getSelectedFrame)(state),
   popupObjectProperties: (0, _selectors.getAllPopupObjectProperties)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(FrameworkComponent);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  setPopupObjectProperties: _actions2.default.setPopupObjectProperties
+})(FrameworkComponent);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.js
@@ -142,9 +142,11 @@ const mapStateToProps = state => {
     isPaused: (0, _selectors.isPaused)(state),
     isLoading: generatedPending || originalPending,
     why: (0, _selectors.getPauseReason)(state),
     originalFrameScopes,
     generatedFrameScopes
   };
 };
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Scopes);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  openLink: _actions2.default.openLink
+})(Scopes);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/index.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/index.js
@@ -403,9 +403,15 @@ const mapStateToProps = state => ({
   breakpointsDisabled: (0, _selectors.getBreakpointsDisabled)(state),
   breakpointsLoading: (0, _selectors.getBreakpointsLoading)(state),
   isWaitingOnBreak: (0, _selectors.getIsWaitingOnBreak)(state),
   shouldPauseOnExceptions: (0, _selectors.getShouldPauseOnExceptions)(state),
   shouldPauseOnCaughtExceptions: (0, _selectors.getShouldPauseOnCaughtExceptions)(state),
   workers: (0, _selectors.getWorkers)(state)
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(SecondaryPanes);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  toggleAllBreakpoints: _actions2.default.toggleAllBreakpoints,
+  toggleShortcutsModal: _actions2.default.toggleShortcutsModal,
+  evaluateExpressions: _actions2.default.evaluateExpressions,
+  pauseOnExceptions: _actions2.default.pauseOnExceptions,
+  breakOnNext: _actions2.default.breakOnNext
+})(SecondaryPanes);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/components/WelcomeBox.js
+++ b/devtools/client/debugger/new/src/components/WelcomeBox.js
@@ -85,9 +85,13 @@ class WelcomeBox extends _react.Componen
 }
 
 exports.WelcomeBox = WelcomeBox;
 
 const mapStateToProps = state => ({
   endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end")
 });
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(WelcomeBox);
\ No newline at end of file
+exports.default = (0, _reactRedux.connect)(mapStateToProps, {
+  togglePaneCollapse: _actions2.default.togglePaneCollapse,
+  setActiveSearch: _actions2.default.setActiveSearch,
+  openQuickOpen: _actions2.default.openQuickOpen
+})(WelcomeBox);
\ No newline at end of file
--- a/devtools/client/debugger/new/src/selectors/breakpointSources.js
+++ b/devtools/client/debugger/new/src/selectors/breakpointSources.js
@@ -19,17 +19,17 @@ var _source = require("../utils/source")
 function getBreakpointsForSource(source, breakpoints) {
   const bpList = breakpoints.valueSeq();
   return bpList.filter(bp => bp.location.sourceId == source.id && !bp.hidden && (bp.text || bp.condition)).sortBy(bp => bp.location.line).toJS();
 }
 
 function findBreakpointSources(sources, breakpoints) {
   const sourceIds = (0, _lodash.uniq)(breakpoints.valueSeq().filter(bp => !bp.hidden).map(bp => bp.location.sourceId).toJS());
   const breakpointSources = sourceIds.map(id => sources[id]).filter(source => source && !source.isBlackBoxed);
-  return (0, _lodash.sortBy)(breakpointSources, source => (0, _source.getFilenameFromURL)(source.url));
+  return (0, _lodash.sortBy)(breakpointSources, source => (0, _source.getFilename)(source));
 }
 
 function _getBreakpointSources(breakpoints, sources) {
   const breakpointSources = findBreakpointSources(sources, breakpoints);
   return breakpointSources.map(source => ({
     source,
     breakpoints: getBreakpointsForSource(source, breakpoints)
   }));
--- a/devtools/client/debugger/new/src/utils/editor/source-documents.js
+++ b/devtools/client/debugger/new/src/utils/editor/source-documents.js
@@ -153,18 +153,19 @@ function showSourceText(editor, source, 
     return;
   }
 
   if (hasDocument(source.id)) {
     const doc = getDocument(source.id);
 
     if (editor.codeMirror.doc === doc) {
       const mode = (0, _source.getMode)(source, symbols);
+      const currentMode = editor.codeMirror.getOption("mode");
 
-      if (doc.mode.name !== mode.name) {
+      if (currentMode.name !== mode.name) {
         editor.setMode(mode);
       }
 
       return;
     }
 
     editor.replaceDocument(doc);
     updateLineNumberFormat(editor, source.id);
--- a/devtools/client/debugger/new/src/utils/source.js
+++ b/devtools/client/debugger/new/src/utils/source.js
@@ -15,33 +15,33 @@ Object.defineProperty(exports, "isMinifi
 });
 exports.shouldPrettyPrint = shouldPrettyPrint;
 exports.isJavaScript = isJavaScript;
 exports.isPretty = isPretty;
 exports.isPrettyURL = isPrettyURL;
 exports.isThirdParty = isThirdParty;
 exports.getPrettySourceURL = getPrettySourceURL;
 exports.getRawSourceURL = getRawSourceURL;
-exports.getFilenameFromURL = getFilenameFromURL;
 exports.getFormattedSourceId = getFormattedSourceId;
 exports.getFilename = getFilename;
+exports.getTruncatedFileName = getTruncatedFileName;
 exports.getFileURL = getFileURL;
 exports.getSourcePath = getSourcePath;
 exports.getSourceLineCount = getSourceLineCount;
 exports.getMode = getMode;
 exports.isLoaded = isLoaded;
 exports.isLoading = isLoading;
 exports.getTextAtPosition = getTextAtPosition;
 exports.getSourceClassnames = getSourceClassnames;
 
 var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
 
 var _utils = require("./utils");
 
-var _path = require("./path");
+var _text = require("../utils/text");
 
 var _url = require("devtools/client/debugger/new/dist/vendors").vendored["url"];
 
 var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"];
 
 var _sourcesTree = require("./sources-tree/index");
 
 const sourceTypes = exports.sourceTypes = {
@@ -148,27 +148,16 @@ function getRawSourceURL(url) {
   return url ? url.replace(/:formatted$/, "") : url;
 }
 
 function resolveFileURL(url, transformUrl = initialUrl => initialUrl) {
   url = getRawSourceURL(url || "");
   const name = transformUrl(url);
   return (0, _utils.endTruncateStr)(name, 50);
 }
-/**
- * Gets a readable filename from a URL for display purposes.
- *
- * @memberof utils/source
- * @static
- */
-
-
-function getFilenameFromURL(url) {
-  return resolveFileURL(url, initialUrl => (0, _devtoolsModules.getUnicodeUrlPath)((0, _path.basename)(initialUrl)) || "(index)");
-}
 
 function getFormattedSourceId(id) {
   const sourceId = id.split("/")[1];
   return `SOURCE${sourceId}`;
 }
 /**
  * Gets a readable filename from a source URL for display purposes.
  * If the source does not have a URL, the source ID will be returned instead.
@@ -183,24 +172,31 @@ function getFilename(source) {
     url,
     id
   } = source;
 
   if (!url) {
     return getFormattedSourceId(id);
   }
 
-  let filename = getFilenameFromURL(url);
-  const qMarkIdx = filename.indexOf("?");
+  const {
+    filename
+  } = (0, _sourcesTree.getURL)(source);
+  return filename;
+}
+/**
+ * Provides a middle-trunated filename
+ *
+ * @memberof utils/source
+ * @static
+ */
 
-  if (qMarkIdx > 0) {
-    filename = filename.slice(0, qMarkIdx);
-  }
 
-  return filename;
+function getTruncatedFileName(source, length = 30) {
+  return (0, _text.truncateMiddleText)(getFilename(source), length);
 }
 /**
  * Gets a readable source URL for display purposes.
  * If the source does not have a URL, the source ID will be returned instead.
  *
  * @memberof utils/source
  * @static
  */
--- a/devtools/client/debugger/new/src/utils/sources-tree/addToTree.js
+++ b/devtools/client/debugger/new/src/utils/sources-tree/addToTree.js
@@ -116,17 +116,17 @@ function addSourceToNode(node, url, sour
 }
 /**
  * @memberof utils/sources-tree
  * @static
  */
 
 
 function addToTree(tree, source, debuggeeUrl, projectRoot) {
-  const url = (0, _getURL.getURL)(source.url, debuggeeUrl);
+  const url = (0, _getURL.getURL)(source, debuggeeUrl);
   const debuggeeHost = (0, _treeOrder.getDomain)(debuggeeUrl);
 
   if ((0, _utils.isInvalidUrl)(url, source)) {
     return;
   }
 
   const finalNode = traverseTree(url, tree, debuggeeHost); // $FlowIgnore
 
--- a/devtools/client/debugger/new/src/utils/sources-tree/getDirectories.js
+++ b/devtools/client/debugger/new/src/utils/sources-tree/getDirectories.js
@@ -32,29 +32,29 @@ function findSource(sourceTree, sourceUr
 
   if (!returnTarget) {
     return sourceTree;
   }
 
   return returnTarget;
 }
 
-function getDirectories(sourceUrl, sourceTree) {
-  const url = (0, _getURL.getURL)(sourceUrl);
+function getDirectories(source, sourceTree) {
+  const url = (0, _getURL.getURL)(source);
   const fullUrl = `${url.group}${url.path}`;
   const parentMap = (0, _utils.createParentMap)(sourceTree);
-  const source = findSource(sourceTree, fullUrl);
+  const subtreeSource = findSource(sourceTree, fullUrl);
 
-  if (!source) {
+  if (!subtreeSource) {
     return [];
   }
 
-  let node = source;
+  let node = subtreeSource;
   const directories = [];
-  directories.push(source);
+  directories.push(subtreeSource);
 
   while (true) {
     node = parentMap.get(node);
 
     if (!node) {
       return directories;
     }
 
--- a/devtools/client/debugger/new/src/utils/sources-tree/getURL.js
+++ b/devtools/client/debugger/new/src/utils/sources-tree/getURL.js
@@ -3,122 +3,136 @@
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.getFilenameFromPath = getFilenameFromPath;
 exports.getURL = getURL;
 
 var _url = require("devtools/client/debugger/new/dist/vendors").vendored["url"];
 
-var _lodash = require("devtools/client/shared/vendor/lodash");
-
 var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"];
 
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
+function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
+
+function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
+
+const urlMap = new WeakMap();
+
 function getFilenameFromPath(pathname) {
   let filename = "";
 
   if (pathname) {
     filename = pathname.substring(pathname.lastIndexOf("/") + 1); // This file does not have a name. Default should be (index).
 
     if (filename == "" || !filename.includes(".")) {
       filename = "(index)";
     }
   }
 
   return filename;
 }
 
 const NoDomain = "(no domain)";
+const def = {
+  path: "",
+  group: "",
+  filename: ""
+};
 
-function getURL(sourceUrl, debuggeeUrl = "") {
-  const url = sourceUrl;
-  const def = {
-    path: "",
-    group: "",
-    filename: ""
-  };
+function _getURL(source, debuggeeUrl) {
+  const {
+    url
+  } = source;
 
   if (!url) {
     return def;
   }
 
   const {
     pathname,
     protocol,
     host,
     path
   } = (0, _url.parse)(url);
-  const defaultDomain = (0, _url.parse)(debuggeeUrl).host;
-  const filename = getFilenameFromPath(pathname);
+  const filename = (0, _devtoolsModules.getUnicodeUrlPath)(getFilenameFromPath(pathname));
 
   switch (protocol) {
     case "javascript:":
       // Ignore `javascript:` URLs for now
       return def;
 
     case "moz-extension:":
     case "resource:":
-      return (0, _lodash.merge)(def, {
+      return _objectSpread({}, def, {
         path,
-        group: `${protocol}//${host || ""}`,
-        filename
+        filename,
+        group: `${protocol}//${host || ""}`
       });
 
     case "webpack:":
     case "ng:":
-      return (0, _lodash.merge)(def, {
+      return _objectSpread({}, def, {
         path: path,
-        group: `${protocol}//`,
-        filename: filename
+        filename,
+        group: `${protocol}//`
       });
 
     case "about:":
       // An about page is a special case
-      return (0, _lodash.merge)(def, {
+      return _objectSpread({}, def, {
         path: "/",
-        group: url,
-        filename: filename
+        filename,
+        group: url
       });
 
     case "data:":
-      return (0, _lodash.merge)(def, {
+      return _objectSpread({}, def, {
         path: "/",
         group: NoDomain,
         filename: url
       });
 
     case null:
       if (pathname && pathname.startsWith("/")) {
         // use file protocol for a URL like "/foo/bar.js"
-        return (0, _lodash.merge)(def, {
+        return _objectSpread({}, def, {
           path: path,
-          group: "file://",
-          filename: filename
+          filename,
+          group: "file://"
         });
       } else if (host === null) {
         // use anonymous group for weird URLs
-        return (0, _lodash.merge)(def, {
+        const defaultDomain = (0, _url.parse)(debuggeeUrl).host;
+        return _objectSpread({}, def, {
           path: url,
           group: defaultDomain,
-          filename: filename
+          filename
         });
       }
 
       break;
 
     case "http:":
     case "https:":
-      return (0, _lodash.merge)(def, {
+      return _objectSpread({}, def, {
         path: pathname,
-        group: (0, _devtoolsModules.getUnicodeHostname)(host),
-        filename: filename
+        filename,
+        group: (0, _devtoolsModules.getUnicodeHostname)(host)
       });
   }
 
-  return (0, _lodash.merge)(def, {
+  return _objectSpread({}, def, {
     path: path,
     group: protocol ? `${protocol}//` : "",
-    filename: filename
+    filename
   });
+}
+
+function getURL(source, debuggeeUrl = "") {
+  if (urlMap.has(source)) {
+    return urlMap.get(source) || def;
+  }
+
+  const url = _getURL(source, debuggeeUrl);
+
+  urlMap.set(source, url);
+  return url;
 }
\ No newline at end of file
--- a/devtools/client/debugger/new/test/mochitest/browser.ini
+++ b/devtools/client/debugger/new/test/mochitest/browser.ini
@@ -224,14 +224,14 @@ skip-if = os == "win" || (verify) # Bug 
 [browser_dbg-sourcemaps-reloading.js]
 [browser_dbg-sourcemaps2.js]
 [browser_dbg-sourcemaps3.js]
 [browser_dbg-sourcemaps-bogus.js]
 skip-if = os == 'linux' && !asan # bug 1447118
 [browser_dbg-sources.js]
 [browser_dbg-sources-named-eval.js]
 [browser_dbg-stepping.js]
-skip-if = debug || (verify && (os == 'win'))
+skip-if = debug || (verify && (os == 'win')) || (os == "win" && os_version == "6.1")
 [browser_dbg-tabs.js]
 [browser_dbg-tabs-pretty-print.js]
 [browser_dbg-toggling-tools.js]
 [browser_dbg-wasm-sourcemaps.js]
 skip-if = true
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -29,16 +29,17 @@
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "BatteryManager.h"
 #include "mozilla/dom/CredentialsContainer.h"
 #include "mozilla/dom/GamepadServiceTest.h"
+#include "mozilla/dom/MediaCapabilities.h"
 #include "mozilla/dom/WakeLock.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/MIDIAccessManager.h"
 #include "mozilla/dom/MIDIOptionsBinding.h"
 #include "mozilla/dom/Permissions.h"
 #include "mozilla/dom/Presentation.h"
 #include "mozilla/dom/ServiceWorkerContainer.h"
 #include "mozilla/dom/StorageManager.h"
@@ -147,16 +148,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCredentials)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaCapabilities)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRServiceTest)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -217,16 +219,18 @@ Navigator::Invalidate()
   }
 
   mVRGetDisplaysPromises.Clear();
 
   if (mVRServiceTest) {
     mVRServiceTest->Shutdown();
     mVRServiceTest = nullptr;
   }
+
+  mMediaCapabilities = nullptr;
 }
 
 void
 Navigator::GetUserAgent(nsAString& aUserAgent, CallerType aCallerType,
                         ErrorResult& aRv) const
 {
   nsCOMPtr<nsPIDOMWindowInner> window;
 
@@ -1790,16 +1794,26 @@ CredentialsContainer*
 Navigator::Credentials()
 {
   if (!mCredentials) {
     mCredentials = new CredentialsContainer(GetWindow());
   }
   return mCredentials;
 }
 
+dom::MediaCapabilities*
+Navigator::MediaCapabilities()
+{
+  if (!mMediaCapabilities) {
+    mMediaCapabilities =
+      new dom::MediaCapabilities(GetWindow()->AsGlobal());
+  }
+  return mMediaCapabilities;
+}
+
 /* static */
 bool
 Navigator::Webdriver()
 {
   return Preferences::GetBool("marionette.enabled", false);
 }
 
 } // namespace dom
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -71,16 +71,17 @@ namespace network {
 class Connection;
 } // namespace network
 
 class Presentation;
 class LegacyMozTCPSocket;
 class VRDisplay;
 class VRServiceTest;
 class StorageManager;
+class MediaCapabilities;
 
 class Navigator final : public nsISupports
                       , public nsWrapperCache
 {
 public:
   explicit Navigator(nsPIDOMWindowInner* aInnerWindow);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -210,16 +211,18 @@ public:
   static bool Webdriver();
 
   void GetLanguages(nsTArray<nsString>& aLanguages);
 
   StorageManager* Storage();
 
   static void GetAcceptLanguages(nsTArray<nsString>& aLanguages);
 
+  dom::MediaCapabilities* MediaCapabilities();
+
   // WebIDL helper methods
   static bool HasUserMediaSupport(JSContext* /* unused */,
                                   JSObject* /* unused */);
 
   nsPIDOMWindowInner* GetParentObject() const
   {
     return GetWindow();
   }
@@ -269,14 +272,15 @@ private:
   RefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
   nsCOMPtr<nsPIDOMWindowInner> mWindow;
   RefPtr<Presentation> mPresentation;
   RefPtr<GamepadServiceTest> mGamepadServiceTest;
   nsTArray<RefPtr<Promise> > mVRGetDisplaysPromises;
   RefPtr<VRServiceTest> mVRServiceTest;
   nsTArray<uint32_t> mRequestedVibrationPattern;
   RefPtr<StorageManager> mStorageManager;
+  RefPtr<dom::MediaCapabilities> mMediaCapabilities;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_Navigator_h
new file mode 100644
--- /dev/null
+++ b/dom/base/ScreenLuminance.cpp
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ScreenLuminance.h"
+#include "nsScreen.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(ScreenLuminance, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(ScreenLuminance, Release)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ScreenLuminance, mScreen)
+
+JSObject*
+ScreenLuminance::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return ScreenLuminance_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/base/ScreenLuminance.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_ScreenLuminance_h
+#define mozilla_dom_ScreenLuminance_h
+
+#include "nsCycleCollectionParticipant.h"
+#include "nsISupportsImpl.h"
+
+class nsScreen;
+
+namespace mozilla {
+namespace dom {
+
+class ScreenLuminance final : public nsWrapperCache
+{
+public:
+  // Ref counting and cycle collection
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ScreenLuminance)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(ScreenLuminance)
+
+  // WebIDL methods
+  double Min() const { return mMin; }
+  double Max() const { return mMax; }
+  double MaxAverage() const { return mMaxAverage; }
+  // End WebIDL methods
+
+  ScreenLuminance(nsScreen* aScreen,
+                  double aMin,
+                  double aMax,
+                  double aMaxAverage)
+    : mScreen(aScreen)
+    , mMin(aMin)
+    , mMax(aMax)
+    , mMaxAverage(aMaxAverage)
+  {
+  }
+
+  nsScreen* GetParentObject() const { return mScreen; }
+  JSObject* WrapObject(JSContext* aCx,
+                       JS::Handle<JSObject*> aGivenProto) override;
+
+private:
+  virtual ~ScreenLuminance() {}
+
+  RefPtr<nsScreen> mScreen;
+  double mMin;
+  double mMax;
+  double mMaxAverage;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_ScreenLuminance_h
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -205,16 +205,17 @@ EXPORTS.mozilla.dom += [
     'PlacesObservers.h',
     'PlacesVisit.h',
     'PlacesWeakCallbackWrapper.h',
     'Pose.h',
     'ProcessGlobal.h',
     'ProcessMessageManager.h',
     'ResponsiveImageSelector.h',
     'SameProcessMessageQueue.h',
+    'ScreenLuminance.h',
     'ScreenOrientation.h',
     'Selection.h',
     'ShadowRoot.h',
     'StructuredCloneBlob.h',
     'StructuredCloneHolder.h',
     'StructuredCloneTags.h',
     'StyleSheetList.h',
     'SubtleCrypto.h',
@@ -354,16 +355,17 @@ UNIFIED_SOURCES += [
     'nsXMLNameSpaceMap.cpp',
     'ParentProcessMessageManager.cpp',
     'Pose.cpp',
     'PostMessageEvent.cpp',
     'ProcessGlobal.cpp',
     'ProcessMessageManager.cpp',
     'ResponsiveImageSelector.cpp',
     'SameProcessMessageQueue.cpp',
+    'ScreenLuminance.cpp',
     'ScreenOrientation.cpp',
     'Selection.cpp',
     'SelectionChangeListener.cpp',
     'ShadowRoot.cpp',
     'StructuredCloneBlob.cpp',
     'StructuredCloneHolder.cpp',
     'StyleSheetList.cpp',
     'SubtleCrypto.cpp',
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -4792,17 +4792,17 @@ nsContentUtils::UnmarkGrayJSListenersInC
 {
   if (!sEventListenerManagersHash) {
     return;
   }
 
   for (auto i = sEventListenerManagersHash->Iter(); !i.Done(); i.Next()) {
     auto entry = static_cast<EventListenerManagerMapEntry*>(i.Get());
     nsINode* n = static_cast<nsINode*>(entry->mListenerManager->GetTarget());
-    if (n && n->IsInUncomposedDoc() &&
+    if (n && n->IsInComposedDoc() &&
         nsCCUncollectableMarker::InGeneration(n->OwnerDoc()->GetMarkedCCGeneration())) {
       entry->mListenerManager->MarkForCC();
     }
   }
 }
 
 /* static */
 void
@@ -7233,17 +7233,17 @@ nsContentUtils::HaveEqualPrincipals(nsID
 /* static */
 bool
 nsContentUtils::HasPluginWithUncontrolledEventDispatch(nsIContent* aContent)
 {
 #ifdef XP_MACOSX
   // We control dispatch to all mac plugins.
   return false;
 #else
-  if (!aContent || !aContent->IsInUncomposedDoc()) {
+  if (!aContent || !aContent->IsInComposedDoc()) {
     return false;
   }
 
   nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(aContent);
   if (!olc) {
     return false;
   }
 
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -3025,24 +3025,24 @@ nsRange::CollectClientRectsAndText(nsLay
   MOZ_ASSERT(IsValidOffset(aStartOffset));
   MOZ_ASSERT(IsValidOffset(aEndOffset));
 
   // Hold strong pointers across the flush
   nsCOMPtr<nsINode> startContainer = aStartContainer;
   nsCOMPtr<nsINode> endContainer = aEndContainer;
 
   // Flush out layout so our frames are up to date.
-  if (!aStartContainer->IsInUncomposedDoc()) {
+  if (!aStartContainer->IsInComposedDoc()) {
     return;
   }
 
   if (aFlushLayout) {
     aStartContainer->OwnerDoc()->FlushPendingNotifications(FlushType::Layout);
     // Recheck whether we're still in the document
-    if (!aStartContainer->IsInUncomposedDoc()) {
+    if (!aStartContainer->IsInComposedDoc()) {
       return;
     }
   }
 
   RangeSubtreeIterator iter;
 
   nsresult rv = iter.Init(aRange);
   if (NS_FAILED(rv)) return;
@@ -3165,17 +3165,17 @@ nsRange::GetUsedFontFaces(nsTArray<nsAut
   nsCOMPtr<nsINode> endContainer = do_QueryInterface(mEnd.Container());
 
   // Flush out layout so our frames are up to date.
   nsIDocument* doc = mStart.Container()->OwnerDoc();
   NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
   doc->FlushPendingNotifications(FlushType::Frames);
 
   // Recheck whether we're still in the document
-  NS_ENSURE_TRUE(mStart.Container()->IsInUncomposedDoc(), NS_ERROR_UNEXPECTED);
+  NS_ENSURE_TRUE(mStart.Container()->IsInComposedDoc(), NS_ERROR_UNEXPECTED);
 
   // A table to map gfxFontEntry objects to InspectorFontFace objects.
   // (We hold on to the InspectorFontFaces strongly due to the nsAutoPtrs
   // in the nsClassHashtable, until we move them out into aResult at the end
   // of the function.)
   nsLayoutUtils::UsedFontFaceTable fontFaces;
 
   RangeSubtreeIterator iter;
--- a/dom/base/nsScreen.cpp
+++ b/dom/base/nsScreen.cpp
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/ScreenBinding.h"
 #include "nsContentUtils.h"
 #include "nsScreen.h"
 #include "nsIDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
 #include "nsCOMPtr.h"
 #include "nsIDocShellTreeItem.h"
--- a/dom/base/nsScreen.h
+++ b/dom/base/nsScreen.h
@@ -2,16 +2,18 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsScreen_h___
 #define nsScreen_h___
 
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/ScreenBinding.h"
+#include "mozilla/dom/ScreenLuminance.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCOMPtr.h"
 #include "nsRect.h"
 
 class nsDeviceContext;
 
@@ -105,16 +107,29 @@ public:
 
   int32_t GetAvailHeight(ErrorResult& aRv)
   {
     nsRect rect;
     aRv = GetAvailRect(rect);
     return rect.Height();
   }
 
+  // Media Capabilities extension
+  mozilla::dom::ScreenColorGamut ColorGamut() const
+  {
+    return mozilla::dom::ScreenColorGamut::Srgb;
+  }
+
+  already_AddRefed<mozilla::dom::ScreenLuminance> GetLuminance() const
+  {
+    return nullptr;
+  }
+
+  IMPL_EVENT_HANDLER(change);
+
   // Deprecated
   void GetMozOrientation(nsString& aOrientation,
                          mozilla::dom::CallerType aCallerType) const;
 
   IMPL_EVENT_HANDLER(mozorientationchange)
 
   bool MozLockOrientation(const nsAString& aOrientation, ErrorResult& aRv);
   bool MozLockOrientation(const mozilla::dom::Sequence<nsString>& aOrientations, ErrorResult& aRv);
--- a/dom/base/test/test_range_bounds.html
+++ b/dom/base/test/test_range_bounds.html
@@ -250,16 +250,32 @@ function testMixedDir(){
 		   bdoRect.left,
 		   firstSpanRect.top, firstSpanRect.bottom,
 		   (firstSpan.firstChild.length - 3) * widthPerChar,
 		   firstSpanRect.height],
 		  [bdoRect.right - 7 * widthPerChar, bdoRect.right,
 		   bdoRect.top, bdoRect.bottom,
 		   7*widthPerChar, bdoRect.height]]});
 }
+
+function testShadowDOM() {
+  var ifr = document.createElement("iframe");
+  document.body.appendChild(ifr);
+  var doc = ifr.contentDocument;
+  var d = doc.createElement("div");
+  var sr = d.attachShadow({mode: "open"});
+  sr.innerHTML = "<div>inside shadow DOM</div>";
+  doc.body.appendChild(d);
+  var r = new ifr.contentWindow.Range();
+  r.selectNode(sr.firstChild);
+  var rect = r.getBoundingClientRect();
+  isnot(rect.width, 0, "Div element inside shadow shouldn't have zero size.");
+  isnot(rect.height, 0, "Div element inside shadow shouldn't have zero size.");
+}
+
 function test(){
   //test ltr
   doTest();
 
   //test rtl
   isLTR = false;
   var root = document.getElementById('content');
   root.dir = 'rtl';
@@ -269,17 +285,21 @@ function test(){
 
   testMixedDir();
 
   //test transforms
   isTransformed = true;
   root.style.transform = "translate(30px,50px)";
   doTest();
 
-  SimpleTest.finish();
+  SpecialPowers.pushPrefEnv({"set":[["dom.webcomponents.shadowdom.enabled", true]]},
+                            () => {
+                              testShadowDOM();
+                              SimpleTest.finish();
+                            });
 }
 
 window.onload = function() {
   SimpleTest.waitForExplicitFinish();
   setTimeout(test, 0);
 };
 
 </script>
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -512,16 +512,20 @@ DOMInterfaces = {
     'nativeType': 'mozilla::extensions::MatchPattern',
 },
 
 'MatchPatternSet': {
     'headerFile': 'mozilla/extensions/MatchPattern.h',
     'nativeType': 'mozilla::extensions::MatchPatternSet',
 },
 
+'MediaCapabilitiesInfo' : {
+    'wrapperCache': False,
+},
+
 'MediaKeys' : {
     'implicitJSContext': [ 'createSession']
 },
 
 'MediaStream': {
     'headerFile': 'DOMMediaStream.h',
     'nativeType': 'mozilla::DOMMediaStream'
 },
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -99,8 +99,10 @@ MSG_DEF(MSG_USELESS_SETTIMEOUT, 1, JSEXN
 MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")
 MSG_DEF(MSG_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache file stream that has already been closed.")
 MSG_DEF(MSG_TIME_VALUE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "{0} is outside the supported range for time values.")
 MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
 MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 0, JSEXN_RANGEERR, "Threshold values must all be in the range [0, 1].")
 MSG_DEF(MSG_WORKER_THREAD_SHUTTING_DOWN, 0, JSEXN_TYPEERR, "The Worker thread is shutting down.")
 MSG_DEF(MSG_CACHE_OPEN_FAILED, 0, JSEXN_TYPEERR, "CacheStorage.open() failed to access the storage system.")
 MSG_DEF(MSG_MATRIX_INIT_LENGTH_WRONG, 1, JSEXN_TYPEERR, "Matrix init sequence must have a length of 6 or 16 (actual value: {0})")
+MSG_DEF(MSG_INVALID_MEDIA_VIDEO_CONFIGURATION, 0, JSEXN_TYPEERR, "Invalid VideoConfiguration.")
+MSG_DEF(MSG_INVALID_MEDIA_AUDIO_CONFIGURATION, 0, JSEXN_TYPEERR, "Invalid AudioConfiguration.")
--- a/dom/browser-element/BrowserElementParent.cpp
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -155,17 +155,17 @@ BrowserElementParent::DispatchOpenWindow
   nsEventStatus status = nsEventStatus_eIgnore;
   bool dispatchSucceeded =
     DispatchCustomDOMEvent(aOpenerFrameElement,
                            NS_LITERAL_STRING("mozbrowseropenwindow"),
                            cx,
                            val, &status);
 
   if (dispatchSucceeded) {
-    if (aPopupFrameElement->IsInUncomposedDoc()) {
+    if (aPopupFrameElement->IsInComposedDoc()) {
       return BrowserElementParent::OPEN_WINDOW_ADDED;
     }
     if (status == nsEventStatus_eConsumeNoDefault) {
       // If the frame was not added to a document, report to callers whether
       // preventDefault was called on or not
       return BrowserElementParent::OPEN_WINDOW_CANCELLED;
     }
   }
--- a/dom/events/PointerEventHandler.cpp
+++ b/dom/events/PointerEventHandler.cpp
@@ -627,17 +627,17 @@ PointerEventHandler::DispatchGotOrLostPo
                        nsIContent* aCaptureTarget)
 {
   nsIDocument* targetDoc = aCaptureTarget->OwnerDoc();
   nsCOMPtr<nsIPresShell> shell = targetDoc->GetShell();
   if (NS_WARN_IF(!shell)) {
     return;
   }
 
-  if (!aIsGotCapture && !aCaptureTarget->IsInUncomposedDoc()) {
+  if (!aIsGotCapture && !aCaptureTarget->IsInComposedDoc()) {
     // If the capturing element was removed from the DOM tree, fire
     // ePointerLostCapture at the document.
     PointerEventInit init;
     init.mPointerId = aPointerEvent->pointerId;
     init.mBubbles = true;
     init.mComposed = true;
     ConvertPointerTypeToString(aPointerEvent->inputSource, init.mPointerType);
     init.mIsPrimary = aPointerEvent->mIsPrimary;
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -7687,17 +7687,17 @@ HTMLMediaElement::MarkAsContentSource(Ca
 
   if (isVisible) {
     // 0 = ALL_VISIBLE
     Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 0);
   } else {
     // 1 = ALL_INVISIBLE
     Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 1);
 
-    if (IsInUncomposedDoc()) {
+    if (IsInComposedDoc()) {
       // 0 = ALL_IN_TREE
       Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT,
                             0);
     } else {
       // 1 = ALL_NOT_IN_TREE
       Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT,
                             1);
     }
@@ -7707,17 +7707,17 @@ HTMLMediaElement::MarkAsContentSource(Ca
     case CallerAPI::DRAW_IMAGE: {
       if (isVisible) {
         // 2 = drawImage_VISIBLE
         Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 2);
       } else {
         // 3 = drawImage_INVISIBLE
         Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 3);
 
-        if (IsInUncomposedDoc()) {
+        if (IsInComposedDoc()) {
           // 2 = drawImage_IN_TREE
           Telemetry::Accumulate(
             Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT, 2);
         } else {
           // 3 = drawImage_NOT_IN_TREE
           Telemetry::Accumulate(
             Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT, 3);
         }
@@ -7727,17 +7727,17 @@ HTMLMediaElement::MarkAsContentSource(Ca
     case CallerAPI::CREATE_PATTERN: {
       if (isVisible) {
         // 4 = createPattern_VISIBLE
         Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 4);
       } else {
         // 5 = createPattern_INVISIBLE
         Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 5);
 
-        if (IsInUncomposedDoc()) {
+        if (IsInComposedDoc()) {
           // 4 = createPattern_IN_TREE
           Telemetry::Accumulate(
             Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT, 4);
         } else {
           // 5 = createPattern_NOT_IN_TREE
           Telemetry::Accumulate(
             Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT, 5);
         }
@@ -7747,17 +7747,17 @@ HTMLMediaElement::MarkAsContentSource(Ca
     case CallerAPI::CREATE_IMAGEBITMAP: {
       if (isVisible) {
         // 6 = createImageBitmap_VISIBLE
         Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 6);
       } else {
         // 7 = createImageBitmap_INVISIBLE
         Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 7);
 
-        if (IsInUncomposedDoc()) {
+        if (IsInComposedDoc()) {
           // 6 = createImageBitmap_IN_TREE
           Telemetry::Accumulate(
             Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT, 6);
         } else {
           // 7 = createImageBitmap_NOT_IN_TREE
           Telemetry::Accumulate(
             Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT, 7);
         }
@@ -7767,17 +7767,17 @@ HTMLMediaElement::MarkAsContentSource(Ca
     case CallerAPI::CAPTURE_STREAM: {
       if (isVisible) {
         // 8 = captureStream_VISIBLE
         Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 8);
       } else {
         // 9 = captureStream_INVISIBLE
         Telemetry::Accumulate(Telemetry::VIDEO_AS_CONTENT_SOURCE, 9);
 
-        if (IsInUncomposedDoc()) {
+        if (IsInComposedDoc()) {
           // 8 = captureStream_IN_TREE
           Telemetry::Accumulate(
             Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT, 8);
         } else {
           // 9 = captureStream_NOT_IN_TREE
           Telemetry::Accumulate(
             Telemetry::VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT, 9);
         }
@@ -7792,17 +7792,17 @@ HTMLMediaElement::MarkAsContentSource(Ca
        isVisible,
        static_cast<int>(aAPI)));
 
   if (!isVisible) {
     LOG(LogLevel::Debug,
         ("%p Log VIDEO_AS_CONTENT_SOURCE_IN_TREE_OR_NOT: inTree = %u, API: "
          "'%d' and 'All'",
          this,
-         IsInUncomposedDoc(),
+         IsInComposedDoc(),
          static_cast<int>(aAPI)));
   }
 }
 
 void
 HTMLMediaElement::UpdateCustomPolicyAfterPlayed()
 {
   OpenUnsupportedMediaWithExternalAppIfNeeded();
@@ -7919,17 +7919,17 @@ HTMLMediaElement::GetEMEInfo(nsString& a
   aEMEInfo.Append(sessionsInfo);
 }
 
 void
 HTMLMediaElement::NotifyDecoderActivityChanges() const
 {
   if (mDecoder) {
     mDecoder->NotifyOwnerActivityChanged(
-      !IsHidden(), mVisibilityState, IsInUncomposedDoc());
+      !IsHidden(), mVisibilityState, IsInComposedDoc());
   }
 }
 
 nsIDocument*
 HTMLMediaElement::GetDocument() const
 {
   return OwnerDoc();
 }
--- a/dom/media/ADTSDecoder.cpp
+++ b/dom/media/ADTSDecoder.cpp
@@ -26,9 +26,24 @@ ADTSDecoder::IsSupportedType(const Media
       aContainerType.Type() == MEDIAMIMETYPE("audio/x-aac")) {
     return IsEnabled() && (aContainerType.ExtendedType().Codecs().IsEmpty() ||
                            aContainerType.ExtendedType().Codecs() == "aac");
   }
 
   return false;
 }
 
+/* static */ nsTArray<UniquePtr<TrackInfo>>
+ADTSDecoder::GetTracksInfo(const MediaContainerType& aType)
+{
+  nsTArray<UniquePtr<TrackInfo>> tracks;
+  if (!IsSupportedType(aType)) {
+    return tracks;
+  }
+
+  tracks.AppendElement(
+    CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+      NS_LITERAL_CSTRING("audio/mp4a-latm"), aType));
+
+  return tracks;
+}
+
 } // namespace mozilla
--- a/dom/media/ADTSDecoder.h
+++ b/dom/media/ADTSDecoder.h
@@ -2,24 +2,30 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ADTS_DECODER_H_
 #define ADTS_DECODER_H_
 
+#include "mozilla/UniquePtr.h"
+#include "nsTArray.h"
+
 namespace mozilla {
 
 class MediaContainerType;
+class TrackInfo;
 
 class ADTSDecoder
 {
 public:
   // Returns true if the ADTS backend is pref'ed on, and we're running on a
   // platform that is likely to have decoders for the format.
   static bool IsEnabled();
   static bool IsSupportedType(const MediaContainerType& aContainerType);
+  static nsTArray<UniquePtr<TrackInfo>> GetTracksInfo(
+    const MediaContainerType& aType);
 };
 
 } // namespace mozilla
 
 #endif // !ADTS_DECODER_H_
--- a/dom/media/Benchmark.cpp
+++ b/dom/media/Benchmark.cpp
@@ -10,16 +10,18 @@
 #include "MediaData.h"
 #include "PDMFactory.h"
 #include "VideoUtils.h"
 #include "WebMDemuxer.h"
 #include "gfxPrefs.h"
 #include "mozilla/AbstractThread.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/SharedThreadPool.h"
+#include "mozilla/StaticMutex.h"
+#include "mozilla/StaticPrefs.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/TaskQueue.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/gfx/gfxVars.h"
 
 #ifndef MOZ_WIDGET_ANDROID
 #include "WebMSample.h"
@@ -34,96 +36,95 @@ namespace mozilla {
 const uint32_t VP9Benchmark::sBenchmarkVersionID = 4;
 
 const char* VP9Benchmark::sBenchmarkFpsPref = "media.benchmark.vp9.fps";
 const char* VP9Benchmark::sBenchmarkFpsVersionCheck = "media.benchmark.vp9.versioncheck";
 bool VP9Benchmark::sHasRunTest = false;
 
 // static
 bool
-VP9Benchmark::IsVP9DecodeFast()
+VP9Benchmark::IsVP9DecodeFast(bool aDefault)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   // Disable VP9 estimizer on Mac, see bug 1400787.
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_APPLEMEDIA)
   return false;
 #else
-  bool hasPref = Preferences::HasUserValue(sBenchmarkFpsPref);
-  uint32_t hadRecentUpdate = Preferences::GetUint(sBenchmarkFpsVersionCheck, 0U);
+  static StaticMutex sMutex;
+  uint32_t decodeFps = StaticPrefs::MediaBenchmarkVp9Fps();
+  uint32_t hadRecentUpdate = StaticPrefs::MediaBenchmarkVp9Versioncheck();
+  bool needBenchmark;
+  {
+    StaticMutexAutoLock lock(sMutex);
+    needBenchmark = !sHasRunTest &&
+                    (decodeFps == 0 || hadRecentUpdate != sBenchmarkVersionID);
+    sHasRunTest = true;
+  }
 
-  if (!sHasRunTest && (!hasPref || hadRecentUpdate != sBenchmarkVersionID)) {
-    sHasRunTest = true;
-
+  if (needBenchmark) {
     RefPtr<WebMDemuxer> demuxer = new WebMDemuxer(
       new BufferMediaResource(sWebMSample, sizeof(sWebMSample)));
-    RefPtr<Benchmark> estimiser =
-      new Benchmark(demuxer,
-                    {
-                      Preferences::GetInt("media.benchmark.frames", 300), // frames to measure
-                      1, // start benchmarking after decoding this frame.
-                      8, // loop after decoding that many frames.
-                      TimeDuration::FromMilliseconds(
-                        Preferences::GetUint("media.benchmark.timeout", 1000))
-                    });
+    RefPtr<Benchmark> estimiser = new Benchmark(
+      demuxer,
+      { StaticPrefs::MediaBenchmarkFrames(), // frames to measure
+        1, // start benchmarking after decoding this frame.
+        8, // loop after decoding that many frames.
+        TimeDuration::FromMilliseconds(StaticPrefs::MediaBenchmarkTimeout()) });
     estimiser->Run()->Then(
-      SystemGroup::AbstractMainThreadFor(TaskCategory::Other), __func__,
+      AbstractThread::MainThread(),
+      __func__,
       [](uint32_t aDecodeFps) {
         if (XRE_IsContentProcess()) {
           dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
           if (contentChild) {
             contentChild->SendNotifyBenchmarkResult(NS_LITERAL_STRING("VP9"),
                                                     aDecodeFps);
           }
         } else {
           Preferences::SetUint(sBenchmarkFpsPref, aDecodeFps);
           Preferences::SetUint(sBenchmarkFpsVersionCheck, sBenchmarkVersionID);
         }
-        Telemetry::Accumulate(Telemetry::HistogramID::VIDEO_VP9_BENCHMARK_FPS, aDecodeFps);
+        Telemetry::Accumulate(Telemetry::HistogramID::VIDEO_VP9_BENCHMARK_FPS,
+                              aDecodeFps);
       },
-      []() { });
+      []() {});
   }
 
-  if (!hasPref) {
-    return false;
+  if (decodeFps == 0) {
+    return aDefault;
   }
 
-  uint32_t decodeFps = Preferences::GetUint(sBenchmarkFpsPref);
-  uint32_t threshold =
-    Preferences::GetUint("media.benchmark.vp9.threshold", 150);
-
-  return decodeFps >= threshold;
+  return decodeFps >= StaticPrefs::MediaBenchmarkVp9Threshold();
 #endif
 }
 
 Benchmark::Benchmark(MediaDataDemuxer* aDemuxer, const Parameters& aParameters)
-  : QueueObject(AbstractThread::MainThread())
+  : QueueObject(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
+                              "Benchmark::QueueObject"))
   , mParameters(aParameters)
   , mKeepAliveUntilComplete(this)
   , mPlaybackState(this, aDemuxer)
 {
   MOZ_COUNT_CTOR(Benchmark);
-  MOZ_ASSERT(Thread(), "Must be run in task queue");
 }
 
 Benchmark::~Benchmark()
 {
   MOZ_COUNT_DTOR(Benchmark);
 }
 
 RefPtr<Benchmark::BenchmarkPromise>
 Benchmark::Run()
 {
-  MOZ_ASSERT(OnThread());
-
-  RefPtr<BenchmarkPromise> p = mPromise.Ensure(__func__);
   RefPtr<Benchmark> self = this;
-  mPlaybackState.Dispatch(NS_NewRunnableFunction(
-    "Benchmark::Run", [self]() { self->mPlaybackState.DemuxSamples(); }));
-  return p;
+  return InvokeAsync(Thread(), __func__, [self] {
+    RefPtr<BenchmarkPromise> p = self->mPromise.Ensure(__func__);
+    self->mPlaybackState.Dispatch(NS_NewRunnableFunction(
+      "Benchmark::Run", [self]() { self->mPlaybackState.DemuxSamples(); }));
+    return p;
+  });
 }
 
 void
 Benchmark::ReturnResult(uint32_t aDecodeFps)
 {
   MOZ_ASSERT(OnThread());
 
   mPromise.ResolveIfExists(aDecodeFps, __func__);
@@ -148,40 +149,39 @@ Benchmark::Dispose()
 void
 Benchmark::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
   gfxVars::Initialize();
   gfxPrefs::GetSingleton();
 }
 
-BenchmarkPlayback::BenchmarkPlayback(Benchmark* aMainThreadState,
+BenchmarkPlayback::BenchmarkPlayback(Benchmark* aGlobalState,
                                      MediaDataDemuxer* aDemuxer)
   : QueueObject(new TaskQueue(
       GetMediaThreadPool(MediaThreadType::PLAYBACK),
       "BenchmarkPlayback::QueueObject"))
-  , mMainThreadState(aMainThreadState)
+  , mGlobalState(aGlobalState)
   , mDecoderTaskQueue(new TaskQueue(
       GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
       "BenchmarkPlayback::mDecoderTaskQueue"))
   , mDemuxer(aDemuxer)
   , mSampleIndex(0)
   , mFrameCount(0)
   , mFinished(false)
   , mDrained(false)
 {
-  MOZ_ASSERT(static_cast<Benchmark*>(mMainThreadState)->OnThread());
 }
 
 void
 BenchmarkPlayback::DemuxSamples()
 {
   MOZ_ASSERT(OnThread());
 
-  RefPtr<Benchmark> ref(mMainThreadState);
+  RefPtr<Benchmark> ref(mGlobalState);
   mDemuxer->Init()->Then(
     Thread(), __func__,
     [this, ref](nsresult aResult) {
       MOZ_ASSERT(OnThread());
       if (mDemuxer->GetNumberTracks(TrackInfo::kVideoTrack)) {
         mTrackDemuxer =
           mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
       } else if (mDemuxer->GetNumberTracks(TrackInfo::kAudioTrack)) {
@@ -197,24 +197,24 @@ BenchmarkPlayback::DemuxSamples()
     [this, ref](const MediaResult& aError) { Error(aError); });
 }
 
 void
 BenchmarkPlayback::DemuxNextSample()
 {
   MOZ_ASSERT(OnThread());
 
-  RefPtr<Benchmark> ref(mMainThreadState);
+  RefPtr<Benchmark> ref(mGlobalState);
   RefPtr<MediaTrackDemuxer::SamplesPromise> promise = mTrackDemuxer->GetSamples();
   promise->Then(
     Thread(), __func__,
     [this, ref](RefPtr<MediaTrackDemuxer::SamplesHolder> aHolder) {
       mSamples.AppendElements(std::move(aHolder->mSamples));
       if (ref->mParameters.mStopAtFrame &&
-          mSamples.Length() == (size_t)ref->mParameters.mStopAtFrame.ref()) {
+          mSamples.Length() == ref->mParameters.mStopAtFrame.ref()) {
         InitDecoder(std::move(*mTrackDemuxer->GetInfo()));
       } else {
         Dispatch(NS_NewRunnableFunction("BenchmarkPlayback::DemuxNextSample",
                                         [this, ref]() { DemuxNextSample(); }));
       }
     },
     [this, ref](const MediaResult& aError) {
       switch (aError.Code()) {
@@ -234,17 +234,17 @@ BenchmarkPlayback::InitDecoder(TrackInfo
   MOZ_ASSERT(OnThread());
 
   RefPtr<PDMFactory> platform = new PDMFactory();
   mDecoder = platform->CreateDecoder({ aInfo, mDecoderTaskQueue });
   if (!mDecoder) {
     Error(MediaResult(NS_ERROR_FAILURE, "Failed to create decoder"));
     return;
   }
-  RefPtr<Benchmark> ref(mMainThreadState);
+  RefPtr<Benchmark> ref(mGlobalState);
   mDecoder->Init()->Then(
     Thread(), __func__,
     [this, ref](TrackInfo::TrackType aTrackType) { InputExhausted(); },
     [this, ref](const MediaResult& aError) { Error(aError); });
 }
 
 void
 BenchmarkPlayback::FinalizeShutdown()
@@ -258,34 +258,34 @@ BenchmarkPlayback::FinalizeShutdown()
 
   if (mTrackDemuxer) {
     mTrackDemuxer->Reset();
     mTrackDemuxer->BreakCycles();
     mTrackDemuxer = nullptr;
   }
   mDemuxer = nullptr;
 
-  RefPtr<Benchmark> ref(mMainThreadState);
+  RefPtr<Benchmark> ref(mGlobalState);
   Thread()->AsTaskQueue()->BeginShutdown()->Then(
     ref->Thread(), __func__,
     [ref]() { ref->Dispose(); },
     []() { MOZ_CRASH("not reached"); });
 }
 
 void
-BenchmarkPlayback::MainThreadShutdown()
+BenchmarkPlayback::GlobalShutdown()
 {
   MOZ_ASSERT(OnThread());
 
   MOZ_ASSERT(!mFinished, "We've already shutdown");
 
   mFinished = true;
 
   if (mDecoder) {
-    RefPtr<Benchmark> ref(mMainThreadState);
+    RefPtr<Benchmark> ref(mGlobalState);
     mDecoder->Flush()->Then(
       Thread(), __func__,
       [ref, this]() {
         mDecoder->Shutdown()->Then(
           Thread(), __func__,
           [ref, this]() {
             FinalizeShutdown();
           },
@@ -299,42 +299,43 @@ BenchmarkPlayback::MainThreadShutdown()
 }
 
 void
 BenchmarkPlayback::Output(const MediaDataDecoder::DecodedData& aResults)
 {
   MOZ_ASSERT(OnThread());
   MOZ_ASSERT(!mFinished);
 
-  RefPtr<Benchmark> ref(mMainThreadState);
+  RefPtr<Benchmark> ref(mGlobalState);
   mFrameCount += aResults.Length();
   if (!mDecodeStartTime && mFrameCount >= ref->mParameters.mStartupFrame) {
     mDecodeStartTime = Some(TimeStamp::Now());
   }
   TimeStamp now = TimeStamp::Now();
-  int32_t frames = mFrameCount - ref->mParameters.mStartupFrame;
+  uint32_t frames = mFrameCount - ref->mParameters.mStartupFrame;
   TimeDuration elapsedTime = now - mDecodeStartTime.refOr(now);
-  if (((frames == ref->mParameters.mFramesToMeasure) && frames > 0) ||
+  if (((frames == ref->mParameters.mFramesToMeasure) &&
+       mFrameCount > ref->mParameters.mStartupFrame && frames > 0) ||
       elapsedTime >= ref->mParameters.mTimeout || mDrained) {
     uint32_t decodeFps = frames / elapsedTime.ToSeconds();
-    MainThreadShutdown();
+    GlobalShutdown();
     ref->Dispatch(
       NS_NewRunnableFunction("BenchmarkPlayback::Output", [ref, decodeFps]() {
         ref->ReturnResult(decodeFps);
       }));
   }
 }
 
 void
 BenchmarkPlayback::Error(const MediaResult& aError)
 {
   MOZ_ASSERT(OnThread());
 
-  RefPtr<Benchmark> ref(mMainThreadState);
-  MainThreadShutdown();
+  RefPtr<Benchmark> ref(mGlobalState);
+  GlobalShutdown();
   ref->Dispatch(NS_NewRunnableFunction(
     "BenchmarkPlayback::Error",
     [ref, aError]() { ref->ReturnError(aError); }));
 }
 
 void
 BenchmarkPlayback::InputExhausted()
 {
@@ -342,17 +343,17 @@ BenchmarkPlayback::InputExhausted()
   MOZ_ASSERT(!mFinished);
 
   if (mSampleIndex >= mSamples.Length()) {
     Error(MediaResult(NS_ERROR_FAILURE, "Nothing left to decode"));
     return;
   }
 
   RefPtr<MediaRawData> sample = mSamples[mSampleIndex];
-  RefPtr<Benchmark> ref(mMainThreadState);
+  RefPtr<Benchmark> ref(mGlobalState);
   RefPtr<MediaDataDecoder::DecodePromise> p = mDecoder->Decode(sample);
 
   mSampleIndex++;
   if (mSampleIndex == mSamples.Length() && !ref->mParameters.mStopAtFrame) {
     // Complete current frame decode then drain if still necessary.
     p->Then(Thread(), __func__,
             [ref, this](const MediaDataDecoder::DecodedData& aResults) {
               Output(aResults);
--- a/dom/media/Benchmark.h
+++ b/dom/media/Benchmark.h
@@ -18,30 +18,30 @@
 namespace mozilla {
 
 class TaskQueue;
 class Benchmark;
 
 class BenchmarkPlayback : public QueueObject
 {
   friend class Benchmark;
-  BenchmarkPlayback(Benchmark* aMainThreadState, MediaDataDemuxer* aDemuxer);
+  BenchmarkPlayback(Benchmark* aGlobalState, MediaDataDemuxer* aDemuxer);
   void DemuxSamples();
   void DemuxNextSample();
-  void MainThreadShutdown();
+  void GlobalShutdown();
   void InitDecoder(TrackInfo&& aInfo);
 
   void Output(const MediaDataDecoder::DecodedData& aResults);
   void Error(const MediaResult& aError);
   void InputExhausted();
 
   // Shutdown trackdemuxer and demuxer if any and shutdown the task queues.
   void FinalizeShutdown();
 
-  Atomic<Benchmark*> mMainThreadState;
+  Atomic<Benchmark*> mGlobalState;
 
   RefPtr<TaskQueue> mDecoderTaskQueue;
   RefPtr<MediaDataDecoder> mDecoder;
 
   // Object only accessed on Thread()
   RefPtr<MediaDataDemuxer> mDemuxer;
   RefPtr<MediaTrackDemuxer> mTrackDemuxer;
   nsTArray<RefPtr<MediaRawData>> mSamples;
@@ -57,45 +57,46 @@ class BenchmarkPlayback : public QueueOb
 class Benchmark : public QueueObject
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Benchmark)
 
   struct Parameters
   {
     Parameters()
-      : mFramesToMeasure(-1)
+      : mFramesToMeasure(UINT32_MAX)
       , mStartupFrame(1)
       , mTimeout(TimeDuration::Forever())
     {
     }
 
-    Parameters(int32_t aFramesToMeasure,
+    Parameters(uint32_t aFramesToMeasure,
                uint32_t aStartupFrame,
-               int32_t aStopAtFrame,
+               uint32_t aStopAtFrame,
                const TimeDuration& aTimeout)
       : mFramesToMeasure(aFramesToMeasure)
       , mStartupFrame(aStartupFrame)
       , mStopAtFrame(Some(aStopAtFrame))
       , mTimeout(aTimeout)
     {
     }
 
-    const int32_t mFramesToMeasure;
+    const uint32_t mFramesToMeasure;
     const uint32_t mStartupFrame;
-    const Maybe<int32_t> mStopAtFrame;
+    const Maybe<uint32_t> mStopAtFrame;
     const TimeDuration mTimeout;
   };
 
   typedef MozPromise<uint32_t, MediaResult, /* IsExclusive = */ true> BenchmarkPromise;
 
   explicit Benchmark(MediaDataDemuxer* aDemuxer,
                      const Parameters& aParameters = Parameters());
   RefPtr<BenchmarkPromise> Run();
 
+  // Must be called on the main thread.
   static void Init();
 
 private:
   friend class BenchmarkPlayback;
   virtual ~Benchmark();
   void ReturnResult(uint32_t aDecodeFps);
   void ReturnError(const MediaResult& aError);
   void Dispose();
@@ -103,17 +104,17 @@ private:
   RefPtr<Benchmark> mKeepAliveUntilComplete;
   BenchmarkPlayback mPlaybackState;
   MozPromiseHolder<BenchmarkPromise> mPromise;
 };
 
 class VP9Benchmark
 {
 public:
-  static bool IsVP9DecodeFast();
+  static bool IsVP9DecodeFast(bool aDefault = false);
   static const char* sBenchmarkFpsPref;
   static const char* sBenchmarkFpsVersionCheck;
   static const uint32_t sBenchmarkVersionID;
   static bool sHasRunTest;
 };
 }
 
 #endif
--- a/dom/media/BitReader.cpp
+++ b/dom/media/BitReader.cpp
@@ -152,9 +152,55 @@ BitReader::FillReservoir()
     mData++;
     mSize--;
   }
 
   mNumBitsLeft = 8 * i;
   mReservoir <<= 32 - mNumBitsLeft;
 }
 
+/* static */ uint32_t
+BitReader::GetBitLength(const mozilla::MediaByteBuffer* aNAL)
+{
+  size_t size = aNAL->Length();
+
+  while (size > 0 && aNAL->ElementAt(size - 1) == 0) {
+    size--;
+  }
+
+  if (!size) {
+    return 0;
+  }
+
+  if (size > UINT32_MAX / 8) {
+    // We can't represent it, we'll use as much as we can.
+    return UINT32_MAX;
+  }
+
+  uint8_t v = aNAL->ElementAt(size - 1);
+  size *= 8;
+
+  // Remove the stop bit and following trailing zeros.
+  if (v) {
+    // Count the consecutive zero bits (trailing) on the right by binary search.
+    // Adapted from Matt Whitlock algorithm to only bother with 8 bits integers.
+    uint32_t c;
+    if (v & 1) {
+      // Special case for odd v (assumed to happen half of the time).
+      c = 0;
+    } else {
+      c = 1;
+      if ((v & 0xf) == 0) {
+        v >>= 4;
+        c += 4;
+      }
+      if ((v & 0x3) == 0) {
+        v >>= 2;
+        c += 2;
+      }
+      c -= v & 0x1;
+    }
+    size -= c + 1;
+  }
+  return size;
+}
+
 } // namespace mozilla
--- a/dom/media/BitReader.h
+++ b/dom/media/BitReader.h
@@ -8,38 +8,41 @@
 #include "MediaData.h"
 
 namespace mozilla
 {
 
 class BitReader
 {
 public:
-  explicit BitReader(const mozilla::MediaByteBuffer* aBuffer);
-  BitReader(const mozilla::MediaByteBuffer* aBuffer, size_t aBits);
+  explicit BitReader(const MediaByteBuffer* aBuffer);
+  BitReader(const MediaByteBuffer* aBuffer, size_t aBits);
   BitReader(const uint8_t* aBuffer, size_t aBits);
   ~BitReader();
   uint32_t ReadBits(size_t aNum);
-  uint32_t ReadBit() { return ReadBits(1); }
+  bool ReadBit() { return ReadBits(1) != 0; }
   uint32_t ReadU32() { return ReadBits(32); }
   uint64_t ReadU64();
 
   // Read the UTF-8 sequence and convert it to its 64-bit UCS-4 encoded form.
   // Return 0xfffffffffffffff if sequence was invalid.
   uint64_t ReadUTF8();
   // Read unsigned integer Exp-Golomb-coded.
   uint32_t ReadUE();
   // Read signed integer Exp-Golomb-coded.
   int32_t ReadSE();
 
   // Return the number of bits parsed so far;
   size_t BitCount() const;
   // Return the number of bits left.
   size_t BitsLeft() const;
 
+  // Return RBSP bit length.
+  static uint32_t GetBitLength(const MediaByteBuffer* aNAL);
+
 private:
   void FillReservoir();
   const uint8_t* mData;
   const size_t mOriginalBitSize;
   size_t mTotalBitsLeft;
   size_t mSize;           // Size left in bytes
   uint32_t mReservoir;    // Left-aligned bits
   size_t mNumBitsLeft;    // Number of bits left in reservoir.
new file mode 100644
--- /dev/null
+++ b/dom/media/BitWriter.cpp
@@ -0,0 +1,96 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BitWriter.h"
+#include "MediaData.h"
+#include "mozilla/MathAlgorithms.h"
+
+namespace mozilla
+{
+
+constexpr uint8_t golombLen[256] = {
+  1,  3,  3,  5,  5,  5,  5,  7,  7,  7,  7,  7,  7,  7,  7,  9,  9,  9,  9,
+  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  11, 11, 11, 11, 11, 11, 11,
+  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+  11, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+  13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+  13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+  13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15,
+  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+  15, 15, 15, 15, 15, 15, 15, 15, 17,
+};
+
+BitWriter::BitWriter(MediaByteBuffer* aBuffer)
+  : mBuffer(aBuffer)
+{
+}
+
+BitWriter::~BitWriter() {}
+
+void
+BitWriter::WriteBits(uint64_t aValue, size_t aBits)
+{
+  MOZ_ASSERT(aBits <= sizeof(uint64_t) * 8);
+
+  while (aBits) {
+    if (mBitIndex == 0) {
+      mBuffer->AppendElement(0);
+    }
+
+    const uint8_t clearMask = ~(~0 << (8 - mBitIndex));
+    uint8_t mask = 0;
+
+    if (mBitIndex + aBits > 8) {
+      // Not enough bits in the current byte to write all the bits
+      // required, we'll process what we can and continue with the left over.
+      const uint8_t leftOverBits = mBitIndex + aBits - 8;
+      const uint64_t leftOver = aValue & (~uint64_t(0) >> (8 - mBitIndex));
+      mask = aValue >> leftOverBits;
+
+      mBitIndex = 8;
+      aValue = leftOver;
+      aBits = leftOverBits;
+    } else {
+      const uint8_t offset = 8 - mBitIndex - aBits;
+      mask = aValue << offset;
+
+      mBitIndex += aBits;
+      aBits = 0;
+    }
+
+    mBuffer->ElementAt(mPosition) |= mask & clearMask;
+
+    if (mBitIndex == 8) {
+      mPosition++;
+      mBitIndex = 0;
+    }
+  }
+}
+
+void
+BitWriter::WriteUE(uint32_t aValue)
+{
+  MOZ_ASSERT(aValue <= (UINT32_MAX - 1));
+
+  if (aValue < 256) {
+    WriteBits(aValue + 1, golombLen[aValue]);
+  } else {
+    const uint32_t e = FloorLog2(aValue + 1);
+    WriteBits(aValue + 1, e * 2 + 1);
+  }
+}
+
+void
+BitWriter::CloseWithRbspTrailing()
+{
+  WriteBit(true);
+  WriteBits(0, (8 - mBitIndex) & 7);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/BitWriter.h
@@ -0,0 +1,43 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef BIT_WRITER_H_
+#define BIT_WRITER_H_
+
+#include "mozilla/RefPtr.h"
+
+namespace mozilla
+{
+
+class MediaByteBuffer;
+
+class BitWriter
+{
+public:
+  explicit BitWriter(MediaByteBuffer* aBuffer);
+  virtual ~BitWriter();
+  void WriteBits(uint64_t aValue, size_t aBits);
+  void WriteBit(bool aValue) { WriteBits(aValue, 1); }
+  void WriteU8(uint8_t aValue) { WriteBits(aValue, 8); }
+  void WriteU32(uint32_t aValue) { WriteBits(aValue, 32); }
+  void WriteU64(uint64_t aValue) { WriteBits(aValue, 64); }
+
+  // Write unsigned integer into Exp-Golomb-coded. 2^32-2 at most
+  void WriteUE(uint32_t aValue);
+
+  // Write RBSP trailing bits.
+  void CloseWithRbspTrailing();
+
+  // Return the number of bits written so far;
+  size_t BitCount() const { return mPosition * 8 + mBitIndex; }
+
+private:
+  RefPtr<MediaByteBuffer> mBuffer;
+  size_t mPosition = 0;
+  uint8_t mBitIndex = 0;
+};
+
+} // namespace mozilla
+
+#endif // BIT_WRITER_H_
--- a/dom/media/DecoderTraits.cpp
+++ b/dom/media/DecoderTraits.cpp
@@ -93,18 +93,18 @@ CanHandleCodecsType(const MediaContainer
     // We can only reach this position if a particular codec was requested,
     // ogg is supported and working: the codec must be invalid.
     return CANPLAY_NO;
   }
   if (WaveDecoder::IsSupportedType(MediaContainerType(mimeType))) {
     if (WaveDecoder::IsSupportedType(aType)) {
       return CANPLAY_YES;
     }
-    // We can only reach this position if a particular codec was requested,
-    // ogg is supported and working: the codec must be invalid.
+    // We can only reach this position if a particular codec was requested, wave
+    // is supported and working: the codec must be invalid or not supported.
     return CANPLAY_NO;
   }
   if (WebMDecoder::IsSupportedType(mimeType)) {
     if (WebMDecoder::IsSupportedType(aType)) {
       return CANPLAY_YES;
     }
     // We can only reach this position if a particular codec was requested,
     // webm is supported and working: the codec must be invalid.
@@ -116,24 +116,39 @@ CanHandleCodecsType(const MediaContainer
     if (MP4Decoder::IsSupportedType(aType, aDiagnostics)) {
       return CANPLAY_YES;
     }
     // We can only reach this position if a particular codec was requested,
     // fmp4 is supported and working: the codec must be invalid.
     return CANPLAY_NO;
   }
 #endif
-  if (MP3Decoder::IsSupportedType(aType)) {
-    return CANPLAY_YES;
+  if (MP3Decoder::IsSupportedType(mimeType)) {
+    if (MP3Decoder::IsSupportedType(aType)) {
+      return CANPLAY_YES;
+    }
+    // We can only reach this position if a particular codec was requested,
+    // mp3 is supported and working: the codec must be invalid.
+    return CANPLAY_NO;
   }
-  if (ADTSDecoder::IsSupportedType(aType)) {
-    return CANPLAY_YES;
+  if (ADTSDecoder::IsSupportedType(mimeType)) {
+    if (ADTSDecoder::IsSupportedType(aType)) {
+      return CANPLAY_YES;
+    }
+    // We can only reach this position if a particular codec was requested,
+    // adts is supported and working: the codec must be invalid.
+    return CANPLAY_NO;
   }
-  if (FlacDecoder::IsSupportedType(aType)) {
-    return CANPLAY_YES;
+  if (FlacDecoder::IsSupportedType(mimeType)) {
+    if (FlacDecoder::IsSupportedType(aType)) {
+      return CANPLAY_YES;
+    }
+    // We can only reach this position if a particular codec was requested,
+    // flac is supported and working: the codec must be invalid.
+    return CANPLAY_NO;
   }
 
   return CANPLAY_MAYBE;
 }
 
 static
 CanPlayStatus
 CanHandleMediaType(const MediaContainerType& aType,
@@ -319,9 +334,41 @@ bool DecoderTraits::IsSupportedInVideoDo
     ADTSDecoder::IsSupportedType(*type) ||
     FlacDecoder::IsSupportedType(*type) ||
 #ifdef MOZ_ANDROID_HLS_SUPPORT
     HLSDecoder::IsSupportedType(*type) ||
 #endif
     false;
 }
 
+/* static */ nsTArray<UniquePtr<TrackInfo>>
+DecoderTraits::GetTracksInfo(const MediaContainerType& aType)
+{
+  // Container type with just the MIME type/subtype, no codecs.
+  const MediaContainerType mimeType(aType.Type());
+
+  if (OggDecoder::IsSupportedType(mimeType)) {
+    return OggDecoder::GetTracksInfo(aType);
+  }
+  if (WaveDecoder::IsSupportedType(mimeType)) {
+    return WaveDecoder::GetTracksInfo(aType);
+  }
+#ifdef MOZ_FMP4
+  if (MP4Decoder::IsSupportedType(mimeType, nullptr)) {
+    return MP4Decoder::GetTracksInfo(aType);
+  }
+#endif
+  if (WebMDecoder::IsSupportedType(mimeType)) {
+    return WebMDecoder::GetTracksInfo(aType);
+  }
+  if (MP3Decoder::IsSupportedType(mimeType)) {
+    return MP3Decoder::GetTracksInfo(aType);
+  }
+  if (ADTSDecoder::IsSupportedType(mimeType)) {
+    return ADTSDecoder::GetTracksInfo(aType);
+  }
+  if (FlacDecoder::IsSupportedType(mimeType)) {
+    return FlacDecoder::GetTracksInfo(aType);
+  }
+  return nsTArray<UniquePtr<TrackInfo>>();
+}
+
 } // namespace mozilla
--- a/dom/media/DecoderTraits.h
+++ b/dom/media/DecoderTraits.h
@@ -2,24 +2,27 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef DecoderTraits_h_
 #define DecoderTraits_h_
 
+#include "mozilla/UniquePtr.h"
 #include "nsStringFwd.h"
+#include "nsTArray.h"
 
 namespace mozilla {
 
 class DecoderDoctorDiagnostics;
 class MediaContainerType;
 struct MediaFormatReaderInit;
 class MediaFormatReader;
+class TrackInfo;
 
 enum CanPlayStatus {
   CANPLAY_NO,
   CANPLAY_MAYBE,
   CANPLAY_YES
 };
 
 class DecoderTraits {
@@ -52,14 +55,18 @@ public:
 
   // Returns true if aType is MIME type of hls.
   static bool IsHttpLiveStreamingType(const MediaContainerType& aType);
 
   // Returns true if aType is matroska type.
   static bool IsMatroskaType(const MediaContainerType& aType);
 
   static bool IsSupportedType(const MediaContainerType& aType);
+
+  // Returns an array of all TrackInfo objects described by this type.
+  static nsTArray<UniquePtr<TrackInfo>> GetTracksInfo(
+    const MediaContainerType& aType);
 };
 
 } // namespace mozilla
 
 #endif
 
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -1,28 +1,28 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaFormatReader.h"
 
-#include "AutoTaskQueue.h"
 #include "MediaData.h"
 #include "MediaInfo.h"
 #include "VideoFrameContainer.h"
 #include "VideoUtils.h"
 #include "mozilla/AbstractThread.h"
 #include "mozilla/CDMProxy.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/SharedThreadPool.h"
 #include "mozilla/StaticPrefs.h"
+#include "mozilla/TaskQueue.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Unused.h"
 #include "nsContentUtils.h"
 #include "nsPrintfCString.h"
 #ifdef MOZ_WIDGET_ANDROID
 #include "mozilla/jni/Utils.h"
 #endif
 
@@ -916,19 +916,19 @@ MediaFormatReader::DecoderFactory::DoIni
 // is itself blocked attempting to access the MediaCache or the MediaResource.
 class MediaFormatReader::DemuxerProxy
 {
   using TrackType = TrackInfo::TrackType;
   class Wrapper;
 
 public:
   explicit DemuxerProxy(MediaDataDemuxer* aDemuxer)
-    : mTaskQueue(new AutoTaskQueue(
-        GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
-        "DemuxerProxy::mTaskQueue"))
+    : mTaskQueue(
+        new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
+                      "DemuxerProxy::mTaskQueue"))
     , mData(new Data(aDemuxer))
   {
     MOZ_COUNT_CTOR(DemuxerProxy);
   }
 
   ~DemuxerProxy()
   {
     MOZ_COUNT_DTOR(DemuxerProxy);
@@ -1011,17 +1011,17 @@ public:
   bool ShouldComputeStartTime() const
   {
     MOZ_RELEASE_ASSERT(mData && mData->mInitDone);
 
     return mData->mShouldComputeStartTime;
   }
 
 private:
-  const RefPtr<AutoTaskQueue> mTaskQueue;
+  const RefPtr<TaskQueue> mTaskQueue;
   struct Data
   {
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Data)
 
     explicit Data(MediaDataDemuxer* aDemuxer)
       : mInitDone(false)
       , mDemuxer(aDemuxer)
     {
@@ -1044,17 +1044,17 @@ private:
     ~Data() { }
   };
   RefPtr<Data> mData;
 };
 
 class MediaFormatReader::DemuxerProxy::Wrapper : public MediaTrackDemuxer
 {
 public:
-  Wrapper(MediaTrackDemuxer* aTrackDemuxer, AutoTaskQueue* aTaskQueue)
+  Wrapper(MediaTrackDemuxer* aTrackDemuxer, TaskQueue* aTaskQueue)
     : mMutex("TrackDemuxer Mutex")
     , mTaskQueue(aTaskQueue)
     , mGetSamplesMayBlock(aTrackDemuxer->GetSamplesMayBlock())
     , mInfo(aTrackDemuxer->GetInfo())
     , mTrackDemuxer(aTrackDemuxer)
   {
     DecoderDoctorLogger::LogConstructionAndBase(
       "MediaFormatReader::DemuxerProxy::Wrapper",
@@ -1161,17 +1161,17 @@ public:
     MutexAutoLock lock(mMutex);
     return mBuffered;
   }
 
   void BreakCycles() override { }
 
 private:
   Mutex mMutex;
-  const RefPtr<AutoTaskQueue> mTaskQueue;
+  const RefPtr<TaskQueue> mTaskQueue;
   const bool mGetSamplesMayBlock;
   const UniquePtr<TrackInfo> mInfo;
   // mTrackDemuxer is only ever accessed on demuxer's task queue.
   RefPtr<MediaTrackDemuxer> mTrackDemuxer;
   // All following members are protected by mMutex
   nsresult mNextRandomAccessPointResult = NS_OK;
   TimeUnit mNextRandomAccessPoint;
   TimeIntervals mBuffered;
@@ -1215,17 +1215,17 @@ private:
 };
 
 RefPtr<MediaDataDemuxer::InitPromise>
 MediaFormatReader::DemuxerProxy::Init()
 {
   using InitPromise = MediaDataDemuxer::InitPromise;
 
   RefPtr<Data> data = mData;
-  RefPtr<AutoTaskQueue> taskQueue = mTaskQueue;
+  RefPtr<TaskQueue> taskQueue = mTaskQueue;
   return InvokeAsync(mTaskQueue, __func__,
                      [data, taskQueue]() {
                        if (!data->mDemuxer) {
                          return InitPromise::CreateAndReject(
                            NS_ERROR_DOM_MEDIA_CANCELED, __func__);
                        }
                        return data->mDemuxer->Init();
                      })
--- a/dom/media/MediaMIMETypes.cpp
+++ b/dom/media/MediaMIMETypes.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaMIMETypes.h"
 
 #include "nsContentTypeParser.h"
+#include "mozilla/dom/MediaCapabilitiesBinding.h"
 
 namespace mozilla {
 
 template <int N>
 static bool
 StartsWith(const nsACString& string, const char (&prefix)[N])
 {
     if (N - 1 > string.Length()) {
@@ -47,18 +48,16 @@ MediaMIMEType::SizeOfExcludingThis(Mallo
 MediaMIMEType::MediaMIMEType(const nsACString& aType)
   : mMIMEType(aType)
 {
 }
 
 Maybe<MediaMIMEType>
 MakeMediaMIMEType(const nsAString& aType)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   nsContentTypeParser parser(aType);
   nsAutoString mime;
   nsresult rv = parser.GetType(mime);
   if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
     return Nothing();
   }
 
   NS_ConvertUTF16toUTF8 mime8{mime};
@@ -143,46 +142,100 @@ GetParameterAsNumber(const nsContentType
   }
   return number;
 }
 
 MediaExtendedMIMEType::MediaExtendedMIMEType(const nsACString& aOriginalString,
                                              const nsACString& aMIMEType,
                                              bool aHaveCodecs,
                                              const nsAString& aCodecs,
-                                             int32_t aWidth, int32_t aHeight,
-                                             int32_t aFramerate, int32_t aBitrate)
+                                             int32_t aWidth,
+                                             int32_t aHeight,
+                                             double aFramerate,
+                                             int32_t aBitrate)
   : mOriginalString(aOriginalString)
   , mMIMEType(aMIMEType)
   , mHaveCodecs(aHaveCodecs)
   , mCodecs(aCodecs)
   , mWidth(aWidth)
   , mHeight(aHeight)
   , mFramerate(aFramerate)
   , mBitrate(aBitrate)
 {
 }
 
+MediaExtendedMIMEType::MediaExtendedMIMEType(const nsACString& aOriginalString,
+                                             const nsACString& aMIMEType,
+                                             bool aHaveCodecs,
+                                             const nsAString& aCodecs,
+                                             int32_t aChannels,
+                                             int32_t aSamplerate,
+                                             int32_t aBitrate)
+  : mOriginalString(aOriginalString)
+  , mMIMEType(aMIMEType)
+  , mHaveCodecs(aHaveCodecs)
+  , mCodecs(aCodecs)
+  , mChannels(aChannels)
+  , mSamplerate(aSamplerate)
+  , mBitrate(aBitrate)
+{
+}
+
 MediaExtendedMIMEType::MediaExtendedMIMEType(const MediaMIMEType& aType)
   : mOriginalString(aType.AsString())
   , mMIMEType(aType)
 {
 }
 
 MediaExtendedMIMEType::MediaExtendedMIMEType(MediaMIMEType&& aType)
   : mOriginalString(aType.AsString())
   , mMIMEType(std::move(aType))
 {
 }
 
+/* static */ Maybe<double>
+MediaExtendedMIMEType::ComputeFractionalString(const nsAString& aFrac)
+{
+  nsAutoString frac(aFrac);
+  nsresult error;
+  double result = frac.ToDouble(&error);
+  if (NS_SUCCEEDED(error)) {
+    if (result <= 0) {
+      return Nothing();
+    }
+    return Some(result);
+  }
+
+  int32_t slashPos = frac.Find(NS_LITERAL_STRING("/"));
+  if (slashPos == kNotFound) {
+    return Nothing();
+  }
+
+  nsAutoString firstPart(Substring(frac, 0, slashPos - 1));
+  double first = firstPart.ToDouble(&error);
+  if (NS_FAILED(error)) {
+    return Nothing();
+  }
+  nsAutoString secondPart(Substring(frac, slashPos + 1));
+  double second = secondPart.ToDouble(&error);
+  if (NS_FAILED(error) || second == 0) {
+    return Nothing();
+  }
+
+  result = first / second;
+  if (result <= 0) {
+    return Nothing();
+  }
+
+  return Some(result);
+}
+
 Maybe<MediaExtendedMIMEType>
 MakeMediaExtendedMIMEType(const nsAString& aType)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   nsContentTypeParser parser(aType);
   nsAutoString mime;
   nsresult rv = parser.GetType(mime);
   if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
     return Nothing();
   }
 
   NS_ConvertUTF16toUTF8 mime8{mime};
@@ -191,26 +244,119 @@ MakeMediaExtendedMIMEType(const nsAStrin
   }
 
   nsAutoString codecs;
   rv = parser.GetParameter("codecs", codecs);
   bool haveCodecs = NS_SUCCEEDED(rv);
 
   int32_t width = GetParameterAsNumber(parser, "width", -1);
   int32_t height = GetParameterAsNumber(parser, "height", -1);
-  int32_t framerate = GetParameterAsNumber(parser, "framerate", -1);
+  double framerate = GetParameterAsNumber(parser, "framerate", -1);
   int32_t bitrate = GetParameterAsNumber(parser, "bitrate", -1);
 
   return Some(MediaExtendedMIMEType(NS_ConvertUTF16toUTF8(aType),
                                     mime8,
                                     haveCodecs, codecs,
                                     width, height,
                                     framerate, bitrate));
 }
 
+Maybe<MediaExtendedMIMEType>
+MakeMediaExtendedMIMEType(const dom::VideoConfiguration& aConfig)
+{
+  MOZ_ASSERT(aConfig.mContentType.WasPassed() &&
+             aConfig.mFramerate.WasPassed() &&
+             aConfig.mWidth.WasPassed() &&
+             aConfig.mHeight.WasPassed() &&
+             aConfig.mBitrate.WasPassed(),
+             "All dictionary members must be present");
+  if (aConfig.mContentType.Value().IsEmpty()) {
+    return Nothing();
+  }
+  nsContentTypeParser parser(aConfig.mContentType.Value());
+  nsAutoString mime;
+  nsresult rv = parser.GetType(mime);
+  if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
+    return Nothing();
+  }
+
+  NS_ConvertUTF16toUTF8 mime8{ mime };
+  if (!IsMediaMIMEType(mime8)) {
+    return Nothing();
+  }
+
+  nsAutoString codecs;
+  rv = parser.GetParameter("codecs", codecs);
+  bool haveCodecs = NS_SUCCEEDED(rv);
+
+  auto framerate =
+    MediaExtendedMIMEType::ComputeFractionalString(aConfig.mFramerate.Value());
+  if (!framerate) {
+    return Nothing();
+  }
+
+  return Some(
+    MediaExtendedMIMEType(NS_ConvertUTF16toUTF8(aConfig.mContentType.Value()),
+                          mime8,
+                          haveCodecs,
+                          codecs,
+                          aConfig.mWidth.Value(),
+                          aConfig.mHeight.Value(),
+                          framerate.ref(),
+                          aConfig.mBitrate.Value()));
+}
+
+Maybe<MediaExtendedMIMEType>
+MakeMediaExtendedMIMEType(const dom::AudioConfiguration& aConfig)
+{
+  if (!aConfig.mContentType.WasPassed() ||
+      aConfig.mContentType.Value().IsEmpty()) {
+    return Nothing();
+  }
+  nsContentTypeParser parser(aConfig.mContentType.Value());
+  nsAutoString mime;
+  nsresult rv = parser.GetType(mime);
+  if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
+    return Nothing();
+  }
+
+  NS_ConvertUTF16toUTF8 mime8{ mime };
+  if (!IsMediaMIMEType(mime8)) {
+    return Nothing();
+  }
+
+  nsAutoString codecs;
+  rv = parser.GetParameter("codecs", codecs);
+  bool haveCodecs = NS_SUCCEEDED(rv);
+
+  int32_t channels = 2; // use a stereo config if not known.
+  if (aConfig.mChannels.WasPassed()) {
+    // A channels string was passed. Make sure it is valid.
+    nsresult error;
+    double value = aConfig.mChannels.Value().ToDouble(&error);
+    if (NS_FAILED(error)) {
+      return Nothing();
+    }
+    // Value is a channel configuration such as 5.1. We want to treat this as 6.
+    channels = value;
+    double fp = value - channels;
+     // round up as .1 and .2 aren't exactly expressible in binary.
+    channels += (fp * 10) + .5;
+  }
+
+  return Some(MediaExtendedMIMEType(
+    NS_ConvertUTF16toUTF8(aConfig.mContentType.Value()),
+    mime8,
+    haveCodecs,
+    codecs,
+    channels,
+    aConfig.mSamplerate.WasPassed() ? aConfig.mSamplerate.Value() : 48000,
+    aConfig.mBitrate.WasPassed() ? aConfig.mBitrate.Value() : 131072));
+}
+
 size_t
 MediaExtendedMIMEType::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
   return mOriginalString.SizeOfExcludingThisIfUnshared(aMallocSizeOf)
          + mMIMEType.SizeOfExcludingThis(aMallocSizeOf)
          + mCodecs.SizeOfExcludingThis(aMallocSizeOf);
 }
 
--- a/dom/media/MediaMIMETypes.h
+++ b/dom/media/MediaMIMETypes.h
@@ -8,16 +8,21 @@
 #define MediaMIMETypes_h_
 
 #include "VideoUtils.h"
 #include "mozilla/Maybe.h"
 #include "nsString.h"
 
 namespace mozilla {
 
+namespace dom {
+struct AudioConfiguration;
+struct VideoConfiguration;
+}
+
 // Class containing pointing at a media MIME "type/subtype" string literal.
 // See IsMediaMIMEType for restrictions.
 // Mainly used to help construct a MediaMIMEType through the statically-checked
 // MEDIAMIMETYPE macro, or to compare a MediaMIMEType to a literal.
 class DependentMediaMIMEType
 {
 public:
   // Construction from a literal. Checked in debug builds.
@@ -170,47 +175,73 @@ public:
   // Was there an explicit 'codecs' parameter provided?
   bool HaveCodecs() const { return mHaveCodecs; }
   // Codecs. May be empty if not provided or explicitly provided as empty.
   const MediaCodecs& Codecs() const { return mCodecs; }
 
   // Sizes and rates.
   Maybe<int32_t> GetWidth() const { return GetMaybeNumber(mWidth); }
   Maybe<int32_t> GetHeight() const { return GetMaybeNumber(mHeight); }
-  Maybe<int32_t> GetFramerate() const { return GetMaybeNumber(mFramerate); }
+  Maybe<double> GetFramerate() const { return GetMaybeNumber(mFramerate); }
   Maybe<int32_t> GetBitrate() const { return GetMaybeNumber(mBitrate); }
+  Maybe<int32_t> GetChannels() const { return GetMaybeNumber(mChannels); }
+  Maybe<int32_t> GetSamplerate() const { return GetMaybeNumber(mSamplerate); }
 
   // Original string. Note that "type/subtype" may not be lowercase,
   // use Type().AsString() instead to get the normalized "type/subtype".
   const nsCString& OriginalString() const { return mOriginalString; }
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
+  // aFrac is either a floating-point number or a fraction made of two
+  // floating-point numbers.
+  static Maybe<double> ComputeFractionalString(const nsAString& aFrac);
+
 private:
   friend Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType(const nsAString& aType);
+  friend Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType(
+    const dom::VideoConfiguration& aConfig);
+  friend Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType(
+    const dom::AudioConfiguration& aConfig);
+
   MediaExtendedMIMEType(const nsACString& aOriginalString,
                         const nsACString& aMIMEType,
                         bool aHaveCodecs, const nsAString& aCodecs,
                         int32_t aWidth, int32_t aHeight,
-                        int32_t aFramerate, int32_t aBitrate);
+                        double aFramerate, int32_t aBitrate);
+  MediaExtendedMIMEType(const nsACString& aOriginalString,
+                        const nsACString& aMIMEType,
+                        bool aHaveCodecs, const nsAString& aCodecs,
+                        int32_t aChannels, int32_t aSamplerate,
+                        int32_t aBitrate);
 
-  Maybe<int32_t> GetMaybeNumber(int32_t aNumber) const
+  template <typename T>
+  Maybe<T> GetMaybeNumber(T aNumber) const
   {
-    return (aNumber < 0) ? Maybe<int32_t>(Nothing()) : Some(int32_t(aNumber));
+    return (aNumber < 0) ? Maybe<T>(Nothing()) : Some(T(aNumber));
   }
 
   nsCString mOriginalString; // Original full string.
   MediaMIMEType mMIMEType; // MIME type/subtype.
   bool mHaveCodecs = false; // If false, mCodecs must be empty.
   MediaCodecs mCodecs;
+  // For video
   int32_t mWidth = -1; // -1 if not provided.
   int32_t mHeight = -1; // -1 if not provided.
-  int32_t mFramerate = -1; // -1 if not provided.
+  double mFramerate = -1; // -1 if not provided.
+  // For audio
+  int32_t mChannels = -1; // -1 if not provided.
+  int32_t mSamplerate = -1; // -1 if not provided.
+  // For both audio and video.
   int32_t mBitrate = -1; // -1 if not provided.
 };
 
 Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType(const nsAString& aType);
 Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType(const nsACString& aType);
 Maybe<MediaExtendedMIMEType> MakeMediaExtendedMIMEType(const char* aType);
+Maybe<MediaExtendedMIMEType>
+MakeMediaExtendedMIMEType(const dom::VideoConfiguration& aConfig);
+Maybe<MediaExtendedMIMEType>
+MakeMediaExtendedMIMEType(const dom::AudioConfiguration& aConfig);
 
 } // namespace mozilla
 
 #endif // MediaMIMETypes_h_
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -1525,16 +1525,20 @@ MediaRecorder::SetOptions(const MediaRec
 
 static char const *const gWebMVideoEncoderCodecs[4] = {
   "opus",
   "vp8",
   "vp8.0",
   // no VP9 yet
   nullptr,
 };
+static char const *const gWebMAudioEncoderCodecs[4] = {
+  "opus",
+  nullptr,
+};
 static char const *const gOggAudioEncoderCodecs[2] = {
   "opus",
   // we could support vorbis here too, but don't
   nullptr,
 };
 
 template <class String>
 static bool
@@ -1573,19 +1577,24 @@ MediaRecorder::IsTypeSupported(const nsA
 
   // effectively a 'switch (mimeType) {'
   if (mimeType.EqualsLiteral(AUDIO_OGG)) {
     if (MediaDecoder::IsOggEnabled() && MediaDecoder::IsOpusEnabled()) {
       codeclist = gOggAudioEncoderCodecs;
     }
   }
 #ifdef MOZ_WEBM_ENCODER
-  else if (mimeType.EqualsLiteral(VIDEO_WEBM) &&
+  else if ((mimeType.EqualsLiteral(VIDEO_WEBM) ||
+            mimeType.EqualsLiteral(AUDIO_WEBM)) &&
            MediaEncoder::IsWebMEncoderEnabled()) {
-    codeclist = gWebMVideoEncoderCodecs;
+    if (mimeType.EqualsLiteral(AUDIO_WEBM)) {
+      codeclist = gWebMAudioEncoderCodecs;
+    } else {
+      codeclist = gWebMVideoEncoderCodecs;
+    }
   }
 #endif
 
   // codecs don't matter if we don't support the container
   if (!codeclist) {
     return false;
   }
   // now filter on codecs, and if needed rescind support
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -412,58 +412,60 @@ bool ExtractVPXCodecDetails(const nsAStr
   // chroma signals. 0 = legal range (e.g. 16-235 for 8 bit sample depth);
   // 1 = full range (e.g. 0-255 for 8-bit sample depth).
   const auto& rangeId = aColorSpace.mRangeId;
   return rangeId <= 1;
 }
 
 bool
 ExtractH264CodecDetails(const nsAString& aCodec,
-                        int16_t& aProfile,
-                        int16_t& aLevel)
+                        uint8_t& aProfile,
+                        uint8_t& aConstraint,
+                        uint8_t& aLevel)
 {
   // H.264 codecs parameters have a type defined as avcN.PPCCLL, where
-  // N = avc type. avc3 is avcc with SPS & PPS implicit (within stream)
+  // N = avc type. avc3 is avcc with SPS & PPS implicit (within stream)
   // PP = profile_idc, CC = constraint_set flags, LL = level_idc.
   // We ignore the constraint_set flags, as it's not clear from any
   // documentation what constraints the platform decoders support.
   // See http://blog.pearce.org.nz/2013/11/what-does-h264avc1-codecs-parameters.html
   // for more details.
   if (aCodec.Length() != strlen("avc1.PPCCLL")) {
     return false;
   }
 
   // Verify the codec starts with "avc1." or "avc3.".
   const nsAString& sample = Substring(aCodec, 0, 5);
   if (!sample.EqualsASCII("avc1.") && !sample.EqualsASCII("avc3.")) {
     return false;
   }
 
-  // Extract the profile_idc and level_idc.
+  // Extract the profile_idc, constraint_flags and level_idc.
   nsresult rv = NS_OK;
   aProfile = PromiseFlatString(Substring(aCodec, 5, 2)).ToInteger(&rv, 16);
   NS_ENSURE_SUCCESS(rv, false);
 
+  // Constraint flags are stored on the 6 most significant bits, first two bits
+  // are reserved_zero_2bits.
+  aConstraint = PromiseFlatString(Substring(aCodec, 7, 2)).ToInteger(&rv, 16);
+  NS_ENSURE_SUCCESS(rv, false);
+
   aLevel = PromiseFlatString(Substring(aCodec, 9, 2)).ToInteger(&rv, 16);
   NS_ENSURE_SUCCESS(rv, false);
 
   if (aLevel == 9) {
     aLevel = H264_LEVEL_1_b;
   } else if (aLevel <= 5) {
     aLevel *= 10;
   }
 
-  // Capture the constraint_set flag value for the purpose of Telemetry.
-  // We don't NS_ENSURE_SUCCESS here because ExtractH264CodecDetails doesn't
-  // care about this, but we make sure constraints is above 4 (constraint_set5_flag)
+  // We only make sure constraints is above 4 for collection perspective
   // otherwise collect 0 for unknown.
-  uint8_t constraints = PromiseFlatString(Substring(aCodec, 7, 2)).ToInteger(&rv, 16);
   Telemetry::Accumulate(Telemetry::VIDEO_CANPLAYTYPE_H264_CONSTRAINT_SET_FLAG,
-                        constraints >= 4 ? constraints : 0);
-
+                        aConstraint >= 4 ? aConstraint : 0);
   // 244 is the highest meaningful profile value (High 4:4:4 Intra Profile)
   // that can be represented as single hex byte, otherwise collect 0 for unknown.
   Telemetry::Accumulate(Telemetry::VIDEO_CANPLAYTYPE_H264_PROFILE,
                         aProfile <= 244 ? aProfile : 0);
 
   // Make sure aLevel represents a value between levels 1 and 5.2,
   // otherwise collect 0 for unknown.
   Telemetry::Accumulate(Telemetry::VIDEO_CANPLAYTYPE_H264_LEVEL,
@@ -654,19 +656,20 @@ StartsWith(const nsACString& string, con
       return false;
     }
     return memcmp(string.Data(), prefix, N - 1) == 0;
 }
 
 bool
 IsH264CodecString(const nsAString& aCodec)
 {
-  int16_t profile = 0;
-  int16_t level = 0;
-  return ExtractH264CodecDetails(aCodec, profile, level);
+  uint8_t profile = 0;
+  uint8_t constraint = 0;
+  uint8_t level = 0;
+  return ExtractH264CodecDetails(aCodec, profile, constraint, level);
 }
 
 bool
 IsAACCodecString(const nsAString& aCodec)
 {
   return
     aCodec.EqualsLiteral("mp4a.40.2") || // MPEG4 AAC-LC
     aCodec.EqualsLiteral("mp4a.40.02") || // MPEG4 AAC-LC(for compatibility)
@@ -726,14 +729,26 @@ CreateTrackInfoWithMIMETypeAndContainerT
       Maybe<int32_t> maybeWidth = aContainerType.ExtendedType().GetWidth();
       if (maybeWidth && *maybeWidth > 0) {
         videoInfo->mImage.width = *maybeWidth;
       }
       Maybe<int32_t> maybeHeight = aContainerType.ExtendedType().GetHeight();
       if (maybeHeight && *maybeHeight > 0) {
         videoInfo->mImage.height = *maybeHeight;
       }
+    } else if (trackInfo->GetAsAudioInfo()) {
+      AudioInfo* audioInfo = trackInfo->GetAsAudioInfo();
+      Maybe<int32_t> maybeChannels =
+        aContainerType.ExtendedType().GetChannels();
+      if (maybeChannels && *maybeChannels > 0) {
+        audioInfo->mChannels = *maybeChannels;
+      }
+      Maybe<int32_t> maybeSamplerate =
+        aContainerType.ExtendedType().GetSamplerate();
+      if (maybeSamplerate && *maybeSamplerate > 0) {
+        audioInfo->mRate = *maybeSamplerate;
+      }
     }
   }
   return trackInfo;
 }
 
 } // end namespace mozilla
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -233,18 +233,19 @@ enum H264_LEVEL {
 // Extracts the H.264/AVC profile and level from an H.264 codecs string.
 // H.264 codecs parameters have a type defined as avc1.PPCCLL, where
 // PP = profile_idc, CC = constraint_set flags, LL = level_idc.
 // See http://blog.pearce.org.nz/2013/11/what-does-h264avc1-codecs-parameters.html
 // for more details.
 // Returns false on failure.
 bool
 ExtractH264CodecDetails(const nsAString& aCodecs,
-                        int16_t& aProfile,
-                        int16_t& aLevel);
+                        uint8_t& aProfile,
+                        uint8_t& aConstraint,
+                        uint8_t& aLevel);
 
 struct VideoColorSpace
 {
   // TODO: Define the value type as strong type enum
   // to better know the exact meaning corresponding to ISO/IEC 23001-8:2016.
   // Default value is listed https://www.webmproject.org/vp9/mp4/#optional-fields
   uint8_t mPrimaryId = 1; // Table 2
   uint8_t mTransferId = 1; // Table 3
--- a/dom/media/flac/FlacDecoder.cpp
+++ b/dom/media/flac/FlacDecoder.cpp
@@ -25,9 +25,24 @@ FlacDecoder::IsEnabled()
 FlacDecoder::IsSupportedType(const MediaContainerType& aContainerType)
 {
   return IsEnabled() &&
          (aContainerType.Type() == MEDIAMIMETYPE("audio/flac") ||
           aContainerType.Type() == MEDIAMIMETYPE("audio/x-flac") ||
           aContainerType.Type() == MEDIAMIMETYPE("application/x-flac"));
 }
 
+/* static */ nsTArray<UniquePtr<TrackInfo>>
+FlacDecoder::GetTracksInfo(const MediaContainerType& aType)
+{
+  nsTArray<UniquePtr<TrackInfo>> tracks;
+  if (!IsSupportedType(aType)) {
+    return tracks;
+  }
+
+  tracks.AppendElement(
+    CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+      NS_LITERAL_CSTRING("audio/flac"), aType));
+
+  return tracks;
+}
+
 } // namespace mozilla
--- a/dom/media/flac/FlacDecoder.h
+++ b/dom/media/flac/FlacDecoder.h
@@ -2,24 +2,30 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef FLAC_DECODER_H_
 #define FLAC_DECODER_H_
 
+#include "mozilla/UniquePtr.h"
+#include "nsTArray.h"
+
 namespace mozilla {
 
 class MediaContainerType;
+class TrackInfo;
 
 class FlacDecoder
 {
 public:
   // Returns true if the Flac backend is pref'ed on, and we're running on a
   // platform that is likely to have decoders for the format.
   static bool IsEnabled();
   static bool IsSupportedType(const MediaContainerType& aContainerType);
+  static nsTArray<UniquePtr<TrackInfo>> GetTracksInfo(
+    const MediaContainerType& aType);
 };
 
 } // namespace mozilla
 
 #endif // !FLAC_DECODER_H_
new file mode 100644
--- /dev/null
+++ b/dom/media/gtest/TestBitWriter.cpp
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gtest/gtest.h"
+#include "BitReader.h"
+#include "BitWriter.h"
+#include "H264.h"
+
+using namespace mozilla;
+
+TEST(BitWriter, BitWriter)
+{
+  RefPtr<MediaByteBuffer> test = new MediaByteBuffer();
+  BitWriter b(test);
+  b.WriteBit(false);
+  b.WriteBits(~1ULL, 1); // ensure that extra bits don't modify byte buffer.
+  b.WriteBits(3, 1);
+  b.WriteUE(1280 / 16 - 1);
+  b.WriteUE(720 / 16 - 1);
+  b.WriteUE(1280);
+  b.WriteUE(720);
+  b.WriteBit(true);
+  b.WriteBit(false);
+  b.WriteBit(true);
+  b.WriteU8(7);
+  b.WriteU32(16356);
+  b.WriteU64(116356);
+  b.WriteBits(~(0ULL) & ~1ULL, 16);
+  const uint32_t length = b.BitCount();
+  b.CloseWithRbspTrailing();
+
+  BitReader c(test);
+
+  EXPECT_EQ(c.ReadBit(), false);
+  EXPECT_EQ(c.ReadBit(), false);
+  EXPECT_EQ(c.ReadBit(), true);
+  EXPECT_EQ(c.ReadUE(), 1280u / 16 - 1);
+  EXPECT_EQ(c.ReadUE(), 720u / 16 - 1);
+  EXPECT_EQ(c.ReadUE(), 1280u);
+  EXPECT_EQ(c.ReadUE(), 720u);
+  EXPECT_EQ(c.ReadBit(), true);
+  EXPECT_EQ(c.ReadBit(), false);
+  EXPECT_EQ(c.ReadBit(), true);
+  EXPECT_EQ(c.ReadBits(8), 7u);
+  EXPECT_EQ(c.ReadU32(), 16356u);
+  EXPECT_EQ(c.ReadU64(), 116356u);
+  EXPECT_EQ(c.ReadBits(16), 0xfffeu);
+  EXPECT_EQ(length, BitReader::GetBitLength(test));
+}
+
+TEST(BitWriter, SPS)
+{
+  uint8_t sps_pps[] = { 0x01, 0x4d, 0x40, 0x0c, 0xff, 0xe1, 0x00, 0x1b, 0x67,
+                        0x4d, 0x40, 0x0c, 0xe8, 0x80, 0x80, 0x9d, 0x80, 0xb5,
+                        0x01, 0x01, 0x01, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40,
+                        0x00, 0x00, 0x0f, 0x03, 0xc5, 0x0a, 0x44, 0x80, 0x01,
+                        0x00, 0x04, 0x68, 0xeb, 0xef, 0x20 };
+
+  RefPtr<MediaByteBuffer> extraData = new MediaByteBuffer();
+  extraData->AppendElements(sps_pps, sizeof(sps_pps));
+  SPSData spsdata1;
+  bool success = H264::DecodeSPSFromExtraData(extraData, spsdata1);
+  EXPECT_EQ(success, true);
+
+  RefPtr<MediaByteBuffer> extraData2 =
+    H264::CreateExtraData(0x42, 0xc0, 0x1e, { 1280, 720 });
+  SPSData spsdata2;
+  success = H264::DecodeSPSFromExtraData(extraData2, spsdata2);
+  EXPECT_EQ(success, true);
+}
--- a/dom/media/gtest/TestMP4Demuxer.cpp
+++ b/dom/media/gtest/TestMP4Demuxer.cpp
@@ -12,18 +12,16 @@
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Unused.h"
 #include "MockMediaResource.h"
 #include "VideoUtils.h"
 
 using namespace mozilla;
 using media::TimeUnit;
 
-class AutoTaskQueue;
-
 #define DO_FAIL [binding]()->void { EXPECT_TRUE(false); binding->mTaskQueue->BeginShutdown(); }
 
 class MP4DemuxerBinding
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MP4DemuxerBinding);
 
   RefPtr<MockMediaResource> resource;
--- a/dom/media/gtest/moz.build
+++ b/dom/media/gtest/moz.build
@@ -7,16 +7,17 @@
 UNIFIED_SOURCES += [
     'MockMediaResource.cpp',
     'TestAudioBuffers.cpp',
     'TestAudioCompactor.cpp',
     'TestAudioMixer.cpp',
     'TestAudioPacketizer.cpp',
     'TestAudioSegment.cpp',
     'TestAudioTrackEncoder.cpp',
+    'TestBitWriter.cpp',
     'TestBlankVideoDataCreator.cpp',
     'TestCDMStorage.cpp',
     'TestDataMutex.cpp',
     'TestGMPCrossOrigin.cpp',
     'TestGMPRemoveAndDelete.cpp',
     'TestGMPUtils.cpp',
     'TestIntervalSet.cpp',
     'TestMediaDataDecoder.cpp',
--- a/dom/media/hls/HLSDemuxer.cpp
+++ b/dom/media/hls/HLSDemuxer.cpp
@@ -127,18 +127,18 @@ public:
   Mutex mMutex;
 private:
   ~HLSDemuxerCallbacksSupport() { }
   HLSDemuxer* mDemuxer;
 
 };
 
 HLSDemuxer::HLSDemuxer(int aPlayerId)
-  : mTaskQueue(new AutoTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
-                                 /* aSupportsTailDispatch = */ false))
+  : mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
+                             /* aSupportsTailDispatch = */ false))
 {
   MOZ_ASSERT(NS_IsMainThread());
   HLSDemuxerCallbacksSupport::Init();
   mJavaCallbacks = GeckoHLSDemuxerWrapper::Callbacks::New();
   MOZ_ASSERT(mJavaCallbacks);
 
   mCallbackSupport = new HLSDemuxerCallbacksSupport(this);
   HLSDemuxerCallbacksSupport::AttachNative(mJavaCallbacks,
--- a/dom/media/hls/HLSDemuxer.h
+++ b/dom/media/hls/HLSDemuxer.h
@@ -2,25 +2,25 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #if !defined(HLSDemuxer_h_)
 #define HLSDemuxer_h_
 
-#include "AutoTaskQueue.h"
 #include "GeneratedJNINatives.h"
 #include "GeneratedJNIWrappers.h"
 #include "MediaCodec.h"
 #include "MediaDataDemuxer.h"
 #include "MediaDecoder.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Mutex.h"
+#include "mozilla/TaskQueue.h"
 
 #include "VideoUtils.h"
 
 namespace mozilla {
 
 class AbstractThread;
 class MediaResult;
 class HLSTrackDemuxer;
@@ -46,28 +46,28 @@ public:
   bool IsSeekable() const override;
 
   UniquePtr<EncryptionInfo> GetCrypto() override;
 
   bool ShouldComputeStartTime() const override { return true; }
 
   void NotifyDataArrived() override;
 
-  AutoTaskQueue* GetTaskQueue() const { return mTaskQueue; }
+  TaskQueue* GetTaskQueue() const { return mTaskQueue; }
   void OnInitialized(bool aHasAudio, bool aHasVideo);
   void OnError(int aErrorCode);
 
 private:
   media::TimeUnit GetNextKeyFrameTime();
 
   bool OnTaskQueue() const;
   ~HLSDemuxer();
   friend class HLSTrackDemuxer;
 
-  const RefPtr<AutoTaskQueue> mTaskQueue;
+  const RefPtr<TaskQueue> mTaskQueue;
   RefPtr<HLSTrackDemuxer> mAudioDemuxer;
   RefPtr<HLSTrackDemuxer> mVideoDemuxer;
 
   MozPromiseHolder<InitPromise> mInitPromise;
   RefPtr<HLSDemuxerCallbacksSupport> mCallbackSupport;
 
   java::GeckoHLSDemuxerWrapper::Callbacks::GlobalRef mJavaCallbacks;
   java::GeckoHLSDemuxerWrapper::GlobalRef mHLSDemuxerWrapper;
new file mode 100644
--- /dev/null
+++ b/dom/media/mediacapabilities/MediaCapabilities.cpp
@@ -0,0 +1,668 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MediaCapabilities.h"
+#include "Benchmark.h"
+#include "DecoderTraits.h"
+#include "Layers.h"
+#include "MediaInfo.h"
+#include "MediaRecorder.h"
+#include "PDMFactory.h"
+#include "VPXDecoder.h"
+#include "mozilla/Move.h"
+#include "mozilla/StaticPrefs.h"
+#include "mozilla/TaskQueue.h"
+#include "mozilla/dom/DOMMozPromiseRequestHolder.h"
+#include "mozilla/dom/MediaCapabilitiesBinding.h"
+#include "mozilla/dom/MediaSource.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/dom/WorkerRef.h"
+#include "mozilla/layers/KnowsCompositor.h"
+#include "nsContentUtils.h"
+
+#include <inttypes.h>
+
+static mozilla::LazyLogModule sMediaCapabilitiesLog("MediaCapabilities");
+
+#define LOG(msg, ...)                                                          \
+  DDMOZ_LOG(sMediaCapabilitiesLog, LogLevel::Debug, msg, ##__VA_ARGS__)
+
+namespace mozilla {
+namespace dom {
+
+static nsCString
+VideoConfigurationToStr(const VideoConfiguration* aConfig)
+{
+  if (!aConfig) {
+    return nsCString();
+  }
+  auto str = nsPrintfCString(
+    "[contentType:%s width:%d height:%d bitrate:%" PRIu64 " framerate:%s]",
+    NS_ConvertUTF16toUTF8(aConfig->mContentType.Value()).get(),
+    aConfig->mWidth.Value(),
+    aConfig->mHeight.Value(),
+    aConfig->mBitrate.Value(),
+    NS_ConvertUTF16toUTF8(aConfig->mFramerate.Value()).get());
+  return std::move(str);
+}
+
+static nsCString
+AudioConfigurationToStr(const AudioConfiguration* aConfig)
+{
+  if (!aConfig) {
+    return nsCString();
+  }
+  auto str = nsPrintfCString(
+    "[contentType:%s channels:%s bitrate:%" PRIu64 " samplerate:%d]",
+    NS_ConvertUTF16toUTF8(aConfig->mContentType.Value()).get(),
+    aConfig->mChannels.WasPassed()
+      ? NS_ConvertUTF16toUTF8(aConfig->mChannels.Value()).get()
+      : "?",
+    aConfig->mBitrate.WasPassed() ? aConfig->mBitrate.Value() : 0,
+    aConfig->mSamplerate.WasPassed() ? aConfig->mSamplerate.Value() : 0);
+  return std::move(str);
+}
+
+static nsCString
+MediaCapabilitiesInfoToStr(const MediaCapabilitiesInfo* aInfo)
+{
+  if (!aInfo) {
+    return nsCString();
+  }
+  auto str = nsPrintfCString("[supported:%s smooth:%s powerEfficient:%s]",
+                             aInfo->Supported() ? "true" : "false",
+                             aInfo->Smooth() ? "true" : "false",
+                             aInfo->PowerEfficient() ? "true" : "false");
+  return std::move(str);
+}
+
+static nsCString
+MediaDecodingConfigurationToStr(const MediaDecodingConfiguration& aConfig)
+{
+  nsCString str;
+  str += NS_LITERAL_CSTRING("[");
+  if (aConfig.mVideo.IsAnyMemberPresent()) {
+    str +=
+      NS_LITERAL_CSTRING("video:") + VideoConfigurationToStr(&aConfig.mVideo);
+    if (aConfig.mAudio.IsAnyMemberPresent()) {
+      str += NS_LITERAL_CSTRING(" ");
+    }
+  }
+  if (aConfig.mAudio.IsAnyMemberPresent()) {
+    str +=
+      NS_LITERAL_CSTRING("audio:") + AudioConfigurationToStr(&aConfig.mAudio);
+  }
+  str += NS_LITERAL_CSTRING("]");
+  return str;
+}
+
+MediaCapabilities::MediaCapabilities(nsIGlobalObject* aParent)
+  : mParent(aParent)
+{
+}
+
+static void
+ThrowWithMemberName(ErrorResult& aRv,
+                    const char* aCategory,
+                    const char* aMember)
+{
+  auto str = nsPrintfCString("'%s' member of %s", aMember, aCategory);
+  aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(
+    NS_ConvertUTF8toUTF16(str));
+}
+
+static void
+CheckVideoConfigurationSanity(const VideoConfiguration& aConfig,
+                              const char* aCategory,
+                              ErrorResult& aRv)
+{
+  if (!aConfig.mContentType.WasPassed()) {
+    ThrowWithMemberName(aRv, "contentType", aCategory);
+    return;
+  }
+  if (!aConfig.mWidth.WasPassed()) {
+    ThrowWithMemberName(aRv, "width", aCategory);
+    return;
+  }
+  if (!aConfig.mHeight.WasPassed()) {
+    ThrowWithMemberName(aRv, "height", aCategory);
+    return;
+  }
+  if (!aConfig.mBitrate.WasPassed()) {
+    ThrowWithMemberName(aRv, "bitrate", aCategory);
+    return;
+  }
+  if (!aConfig.mFramerate.WasPassed()) {
+    ThrowWithMemberName(aRv, "framerate", aCategory);
+    return;
+  }
+}
+
+static void
+CheckAudioConfigurationSanity(const AudioConfiguration& aConfig,
+                              const char* aCategory,
+                              ErrorResult& aRv)
+{
+  if (!aConfig.mContentType.WasPassed()) {
+    ThrowWithMemberName(aRv, "contentType", aCategory);
+    return;
+  }
+}
+
+already_AddRefed<Promise>
+MediaCapabilities::DecodingInfo(
+  const MediaDecodingConfiguration& aConfiguration,
+  ErrorResult& aRv)
+{
+  RefPtr<Promise> promise = Promise::Create(mParent, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  // If configuration is not a valid MediaConfiguration, return a Promise
+  // rejected with a TypeError.
+  if (!aConfiguration.IsAnyMemberPresent() ||
+      (!aConfiguration.mVideo.IsAnyMemberPresent() &&
+       !aConfiguration.mAudio.IsAnyMemberPresent())) {
+    aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(
+      NS_LITERAL_STRING("'audio' or 'video'"));
+    return nullptr;
+  }
+
+  // Here we will throw rather than rejecting a promise in order to simulate
+  // optional dictionaries with required members (see bug 1368949)
+  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
+    // Check that all VideoConfiguration required members are present.
+    CheckVideoConfigurationSanity(
+      aConfiguration.mVideo, "MediaDecodingConfiguration", aRv);
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+  }
+  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
+    // Check that all AudioConfiguration required members are present.
+    CheckAudioConfigurationSanity(
+      aConfiguration.mAudio, "MediaDecodingConfiguration", aRv);
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+  }
+
+  LOG("Processing %s", MediaDecodingConfigurationToStr(aConfiguration).get());
+
+  bool supported = true;
+  Maybe<MediaContainerType> videoContainer;
+  Maybe<MediaContainerType> audioContainer;
+
+  // If configuration.video is present and is not a valid video configuration,
+  // return a Promise rejected with a TypeError.
+  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
+    videoContainer = CheckVideoConfiguration(aConfiguration.mVideo);
+    if (!videoContainer) {
+      aRv.ThrowTypeError<MSG_INVALID_MEDIA_VIDEO_CONFIGURATION>();
+      return nullptr;
+    }
+
+    // We have a video configuration and it is valid. Check if it is supported.
+    supported &=
+      aConfiguration.mType == MediaDecodingType::File
+        ? CheckTypeForFile(aConfiguration.mVideo.mContentType.Value())
+        : CheckTypeForMediaSource(aConfiguration.mVideo.mContentType.Value());
+  }
+  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
+    audioContainer = CheckAudioConfiguration(aConfiguration.mAudio);
+    if (!audioContainer) {
+      aRv.ThrowTypeError<MSG_INVALID_MEDIA_AUDIO_CONFIGURATION>();
+      return nullptr;
+    }
+    // We have an audio configuration and it is valid. Check if it is supported.
+    supported &=
+      aConfiguration.mType == MediaDecodingType::File
+        ? CheckTypeForFile(aConfiguration.mAudio.mContentType.Value())
+        : CheckTypeForMediaSource(aConfiguration.mAudio.mContentType.Value());
+  }
+
+  if (!supported) {
+    auto info = MakeUnique<MediaCapabilitiesInfo>(
+      false /* supported */, false /* smooth */, false /* power efficient */);
+    LOG("%s -> %s",
+        MediaDecodingConfigurationToStr(aConfiguration).get(),
+        MediaCapabilitiesInfoToStr(info.get()).get());
+    promise->MaybeResolve(std::move(info));
+    return promise.forget();
+  }
+
+  nsTArray<UniquePtr<TrackInfo>> tracks;
+  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
+    MOZ_ASSERT(videoContainer.isSome(), "configuration is valid and supported");
+    auto videoTracks = DecoderTraits::GetTracksInfo(*videoContainer);
+    // If the MIME type does not imply a codec, the string MUST
+    // also have one and only one parameter that is named codecs with a value
+    // describing a single media codec. Otherwise, it MUST contain no
+    // parameters.
+    if (videoTracks.Length() != 1) {
+      promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
+      return promise.forget();
+    }
+    MOZ_DIAGNOSTIC_ASSERT(videoTracks.ElementAt(0),
+                          "must contain a valid trackinfo");
+    tracks.AppendElements(std::move(videoTracks));
+  }
+  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
+    MOZ_ASSERT(audioContainer.isSome(), "configuration is valid and supported");
+    auto audioTracks = DecoderTraits::GetTracksInfo(*audioContainer);
+    // If the MIME type does not imply a codec, the string MUST
+    // also have one and only one parameter that is named codecs with a value
+    // describing a single media codec. Otherwise, it MUST contain no
+    // parameters.
+    if (audioTracks.Length() != 1) {
+      promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
+      return promise.forget();
+    }
+    MOZ_DIAGNOSTIC_ASSERT(audioTracks.ElementAt(0),
+                          "must contain a valid trackinfo");
+    tracks.AppendElements(std::move(audioTracks));
+  }
+
+  typedef MozPromise<MediaCapabilitiesInfo,
+                     MediaResult,
+                     /* IsExclusive = */ true>
+    CapabilitiesPromise;
+  nsTArray<RefPtr<CapabilitiesPromise>> promises;
+
+  RefPtr<TaskQueue> taskQueue =
+    new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
+                  "MediaCapabilities::TaskQueue");
+  for (auto&& config : tracks) {
+    TrackInfo::TrackType type =
+      config->IsVideo() ? TrackInfo::kVideoTrack : TrackInfo::kAudioTrack;
+
+    MOZ_ASSERT(type == TrackInfo::kAudioTrack ||
+                 videoContainer->ExtendedType().GetFramerate().isSome(),
+               "framerate is a required member of VideoConfiguration");
+
+    if (type == TrackInfo::kAudioTrack) {
+      // There's no need to create an audio decoder has we only want to know if
+      // such codec is supported
+      RefPtr<PDMFactory> pdm = new PDMFactory();
+      if (!pdm->Supports(*config, nullptr /* decoder doctor */)) {
+        auto info =
+          MakeUnique<MediaCapabilitiesInfo>(false /* supported */,
+                                            false /* smooth */,
+                                            false /* power efficient */);
+        LOG("%s -> %s",
+            MediaDecodingConfigurationToStr(aConfiguration).get(),
+            MediaCapabilitiesInfoToStr(info.get()).get());
+        promise->MaybeResolve(std::move(info));
+        return promise.forget();
+      }
+      // We can assume that if we could create the decoder, then we can play it.
+      // We report that we can play it smoothly and in an efficient fashion.
+      promises.AppendElement(CapabilitiesPromise::CreateAndResolve(
+        MediaCapabilitiesInfo(
+          true /* supported */, true /* smooth */, true /* power efficient */),
+        __func__));
+      continue;
+    }
+
+    // On Windows, the MediaDataDecoder expects to be created on a thread
+    // supporting MTA, which the main thread doesn't. So we use our task queue
+    // to create such decoder and perform initialization.
+
+    RefPtr<layers::KnowsCompositor> compositor = GetCompositor();
+    double frameRate = videoContainer->ExtendedType().GetFramerate().ref();
+    promises.AppendElement(InvokeAsync(
+      taskQueue,
+      __func__,
+      [taskQueue, frameRate, compositor, config = std::move(config)]() mutable
+      -> RefPtr<CapabilitiesPromise> {
+        // MediaDataDecoder keeps a reference to the config object, so we must
+        // keep it alive until the decoder has been shutdown.
+        CreateDecoderParams params{ *config,
+                                    taskQueue,
+                                    compositor,
+                                    CreateDecoderParams::VideoFrameRate(
+                                      frameRate),
+                                    TrackInfo::kVideoTrack };
+
+        RefPtr<PDMFactory> pdm = new PDMFactory();
+        RefPtr<MediaDataDecoder> decoder = pdm->CreateDecoder(params);
+        if (!decoder) {
+          return CapabilitiesPromise::CreateAndReject(
+            MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "Can't create decoder"),
+            __func__);
+        }
+        // We now query the decoder to determine if it's power efficient.
+        return decoder->Init()->Then(
+          taskQueue,
+          __func__,
+          [taskQueue, decoder, frameRate, config = std::move(config)](
+            const MediaDataDecoder::InitPromise::ResolveOrRejectValue&
+              aValue) mutable {
+            RefPtr<CapabilitiesPromise> p;
+            if (aValue.IsReject()) {
+              p = CapabilitiesPromise::CreateAndReject(aValue.RejectValue(),
+                                                       __func__);
+            } else {
+              MOZ_ASSERT(config->IsVideo());
+              nsAutoCString reason;
+              bool powerEfficient = true;
+              bool smooth = true;
+              if (config->GetAsVideoInfo()->mImage.height > 480) {
+                // Assume that we can do stuff at 480p or less in a power
+                // efficient manner and smoothly. If greater than 480p we assume
+                // that if the video decoding is hardware accelerated it will be
+                // smooth and power efficient, otherwise we use the benchmark to
+                // estimate
+                powerEfficient = decoder->IsHardwareAccelerated(reason);
+                if (!powerEfficient && VPXDecoder::IsVP9(config->mMimeType)) {
+                  smooth = VP9Benchmark::IsVP9DecodeFast(true /* default */);
+                  uint32_t fps = StaticPrefs::MediaBenchmarkVp9Fps();
+                  if (!smooth && fps > 0) {
+                    // The VP9 estimizer decode a 1280x720 video. Let's adjust
+                    // the result for the resolution and frame rate of what we
+                    // actually want. If the result is twice that we need we
+                    // assume it will be smooth.
+                    const auto& videoConfig = *config->GetAsVideoInfo();
+                    double needed =
+                      ((1280.0 * 720.0) /
+                       (videoConfig.mImage.width * videoConfig.mImage.height) *
+                       fps) /
+                      frameRate;
+                    smooth = needed > 2;
+                  }
+                }
+              }
+              p = CapabilitiesPromise::CreateAndResolve(
+                MediaCapabilitiesInfo(
+                  true /* supported */, smooth, powerEfficient),
+                __func__);
+            }
+            MOZ_ASSERT(p.get(), "the promise has been created");
+            // Let's keep alive the decoder and the config object until the
+            // decoder has shutdown.
+            decoder->Shutdown()->Then(
+              taskQueue,
+              __func__,
+              [taskQueue, decoder, config = std::move(config)](
+                const ShutdownPromise::ResolveOrRejectValue& aValue) {});
+            return p;
+          });
+      }));
+  }
+
+  auto holder =
+    MakeRefPtr<DOMMozPromiseRequestHolder<CapabilitiesPromise::AllPromiseType>>(
+      mParent);
+  RefPtr<nsISerialEventTarget> targetThread;
+  RefPtr<StrongWorkerRef> workerRef;
+
+  if (NS_IsMainThread()) {
+    targetThread = mParent->AbstractMainThreadFor(TaskCategory::Other);
+  } else {
+    WorkerPrivate* wp = GetCurrentThreadWorkerPrivate();
+    MOZ_ASSERT(wp, "Must be called from a worker thread");
+    targetThread = wp->HybridEventTarget();
+    RefPtr<StrongWorkerRef> strongWorkerRef = StrongWorkerRef::Create(
+      wp, "MediaCapabilities", [holder, targetThread]() {
+        MOZ_ASSERT(targetThread->IsOnCurrentThread());
+        holder->DisconnectIfExists();
+      });
+    if (NS_WARN_IF(!workerRef)) {
+      // The worker is shutting down.
+      aRv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
+  }
+
+  MOZ_ASSERT(targetThread);
+
+  // this is only captured for use with the LOG macro.
+  RefPtr<MediaCapabilities> self = this;
+
+  CapabilitiesPromise::All(targetThread, promises)
+    ->Then(
+      targetThread,
+      __func__,
+      [promise,
+       tracks = std::move(tracks),
+       workerRef,
+       holder,
+       aConfiguration,
+       self,
+       this](const CapabilitiesPromise::AllPromiseType::ResolveOrRejectValue&
+               aValue) {
+        holder->Complete();
+        if (aValue.IsReject()) {
+          auto info =
+            MakeUnique<MediaCapabilitiesInfo>(false /* supported */,
+                                              false /* smooth */,
+                                              false /* power efficient */);
+          LOG("%s -> %s",
+              MediaDecodingConfigurationToStr(aConfiguration).get(),
+              MediaCapabilitiesInfoToStr(info.get()).get());
+          promise->MaybeResolve(std::move(info));
+          return;
+        }
+        bool powerEfficient = true;
+        bool smooth = true;
+        for (auto&& capability : aValue.ResolveValue()) {
+          smooth &= capability.Smooth();
+          powerEfficient &= capability.PowerEfficient();
+        }
+        auto info = MakeUnique<MediaCapabilitiesInfo>(
+          true /* supported */, smooth, powerEfficient);
+        LOG("%s -> %s",
+            MediaDecodingConfigurationToStr(aConfiguration).get(),
+            MediaCapabilitiesInfoToStr(info.get()).get());
+        promise->MaybeResolve(std::move(info));
+      })
+    ->Track(*holder);
+
+  return promise.forget();
+}
+
+already_AddRefed<Promise>
+MediaCapabilities::EncodingInfo(
+  const MediaEncodingConfiguration& aConfiguration,
+  ErrorResult& aRv)
+{
+  RefPtr<Promise> promise = Promise::Create(mParent, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  // If configuration is not a valid MediaConfiguration, return a Promise
+  // rejected with a TypeError.
+  if (!aConfiguration.IsAnyMemberPresent() ||
+      (!aConfiguration.mVideo.IsAnyMemberPresent() &&
+       !aConfiguration.mAudio.IsAnyMemberPresent())) {
+    aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(
+      NS_LITERAL_STRING("'audio' or 'video'"));
+    return nullptr;
+  }
+
+  // Here we will throw rather than rejecting a promise in order to simulate
+  // optional dictionaries with required members (see bug 1368949)
+  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
+    // Check that all VideoConfiguration required members are present.
+    CheckVideoConfigurationSanity(
+      aConfiguration.mVideo, "MediaDecodingConfiguration", aRv);
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+  }
+  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
+    // Check that all AudioConfiguration required members are present.
+    CheckAudioConfigurationSanity(
+      aConfiguration.mAudio, "MediaDecodingConfiguration", aRv);
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+  }
+
+  bool supported = true;
+
+  // If configuration.video is present and is not a valid video configuration,
+  // return a Promise rejected with a TypeError.
+  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
+    if (!CheckVideoConfiguration(aConfiguration.mVideo)) {
+      aRv.ThrowTypeError<MSG_INVALID_MEDIA_VIDEO_CONFIGURATION>();
+      return nullptr;
+    }
+    // We have a video configuration and it is valid. Check if it is supported.
+    supported &=
+      CheckTypeForEncoder(aConfiguration.mVideo.mContentType.Value());
+  }
+  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
+    if (!CheckAudioConfiguration(aConfiguration.mAudio)) {
+      aRv.ThrowTypeError<MSG_INVALID_MEDIA_AUDIO_CONFIGURATION>();
+      return nullptr;
+    }
+    // We have an audio configuration and it is valid. Check if it is supported.
+    supported &=
+      CheckTypeForEncoder(aConfiguration.mAudio.mContentType.Value());
+  }
+
+  auto info = MakeUnique<MediaCapabilitiesInfo>(supported, supported, false);
+  promise->MaybeResolve(std::move(info));
+
+  return promise.forget();
+}
+
+Maybe<MediaContainerType>
+MediaCapabilities::CheckVideoConfiguration(
+  const VideoConfiguration& aConfig) const
+{
+  Maybe<MediaExtendedMIMEType> container = MakeMediaExtendedMIMEType(aConfig);
+  if (!container) {
+    return Nothing();
+  }
+  // A valid video MIME type is a string that is a valid media MIME type and for
+  // which the type per [RFC7231] is either video or application.
+  if (!container->Type().HasVideoMajorType() &&
+      !container->Type().HasApplicationMajorType()) {
+    return Nothing();
+  }
+
+  // If the MIME type does not imply a codec, the string MUST also have one and
+  // only one parameter that is named codecs with a value describing a single
+  // media codec. Otherwise, it MUST contain no parameters.
+  // TODO (nsIMOMEHeaderParam doesn't provide backend to count number of
+  // parameters)
+
+  return Some(MediaContainerType(std::move(*container)));
+}
+
+Maybe<MediaContainerType>
+MediaCapabilities::CheckAudioConfiguration(
+  const AudioConfiguration& aConfig) const
+{
+  Maybe<MediaExtendedMIMEType> container = MakeMediaExtendedMIMEType(aConfig);
+  if (!container) {
+    return Nothing();
+  }
+  // A valid audio MIME type is a string that is valid media MIME type and for
+  // which the type per [RFC7231] is either audio or application.
+  if (!container->Type().HasAudioMajorType() &&
+      !container->Type().HasApplicationMajorType()) {
+    return Nothing();
+  }
+
+  // If the MIME type does not imply a codec, the string MUST also have one and
+  // only one parameter that is named codecs with a value describing a single
+  // media codec. Otherwise, it MUST contain no parameters.
+  // TODO (nsIMOMEHeaderParam doesn't provide backend to count number of
+  // parameters)
+
+  return Some(MediaContainerType(std::move(*container)));
+}
+
+bool
+MediaCapabilities::CheckTypeForMediaSource(const nsAString& aType)
+{
+  return NS_SUCCEEDED(MediaSource::IsTypeSupported(
+    aType, nullptr /* DecoderDoctorDiagnostics */));
+}
+
+bool
+MediaCapabilities::CheckTypeForFile(const nsAString& aType)
+{
+  Maybe<MediaContainerType> containerType = MakeMediaContainerType(aType);
+  if (!containerType) {
+    return false;
+  }
+
+  return DecoderTraits::CanHandleContainerType(
+           *containerType, nullptr /* DecoderDoctorDiagnostics */) !=
+         CANPLAY_NO;
+}
+
+bool
+MediaCapabilities::CheckTypeForEncoder(const nsAString& aType)
+{
+  return MediaRecorder::IsTypeSupported(aType);
+}
+
+already_AddRefed<layers::KnowsCompositor>
+MediaCapabilities::GetCompositor()
+{
+  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetParentObject());
+  if (NS_WARN_IF(!window)) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
+  if (NS_WARN_IF(!doc)) {
+    return nullptr;
+  }
+  RefPtr<layers::LayerManager> layerManager =
+    nsContentUtils::LayerManagerForDocument(doc);
+  if (NS_WARN_IF(!layerManager)) {
+    return nullptr;
+  }
+  RefPtr<layers::KnowsCompositor> knows = layerManager->AsKnowsCompositor();
+  if (NS_WARN_IF(!knows)) {
+    return nullptr;
+  }
+  return knows->GetForMedia().forget();
+}
+
+bool
+MediaCapabilities::Enabled(JSContext* aCx, JSObject* aGlobal)
+{
+  return StaticPrefs::MediaCapabilitiesEnabled();
+}
+
+JSObject*
+MediaCapabilities::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return MediaCapabilities_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaCapabilities)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaCapabilities)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaCapabilities)
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaCapabilities, mParent)
+
+// MediaCapabilitiesInfo
+bool
+MediaCapabilitiesInfo::WrapObject(JSContext* aCx,
+                                  JS::Handle<JSObject*> aGivenProto,
+                                  JS::MutableHandle<JSObject*> aReflector)
+{
+  return MediaCapabilitiesInfo_Binding::Wrap(
+    aCx, this, aGivenProto, aReflector);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/mediacapabilities/MediaCapabilities.h
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_MediaCapabilities_h_
+#define mozilla_dom_MediaCapabilities_h_
+
+#include "DecoderDoctorLogger.h"
+#include "MediaContainerType.h"
+#include "js/TypeDecls.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "nsCOMPtr.h"
+#include "nsCycleCollectionNoteChild.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsIGlobalObject.h"
+#include "nsISupports.h"
+#include "nsWrapperCache.h"
+
+namespace mozilla {
+namespace layers {
+class KnowsCompositor;
+}
+namespace dom {
+class MediaCapabilities;
+} // namespace dom
+DDLoggedTypeName(dom::MediaCapabilities);
+
+namespace dom {
+
+struct MediaDecodingConfiguration;
+struct MediaEncodingConfiguration;
+struct AudioConfiguration;
+struct VideoConfiguration;
+class Promise;
+
+class MediaCapabilities final
+  : public nsISupports
+  , public nsWrapperCache
+{
+public:
+  // Ref counting and cycle collection
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaCapabilities)
+
+  // WebIDL Methods
+  already_AddRefed<Promise> DecodingInfo(
+    const MediaDecodingConfiguration& aConfiguration,
+    ErrorResult& aRv);
+  already_AddRefed<Promise> EncodingInfo(
+    const MediaEncodingConfiguration& aConfiguration,
+    ErrorResult& aRv);
+  // End WebIDL Methods
+
+  explicit MediaCapabilities(nsIGlobalObject* aParent);
+
+  nsIGlobalObject* GetParentObject() const { return mParent; }
+  JSObject* WrapObject(JSContext* aCx,
+                       JS::Handle<JSObject*> aGivenProto) override;
+
+  static bool Enabled(JSContext* aCx, JSObject* aGlobal);
+
+private:
+  virtual ~MediaCapabilities() = default;
+  Maybe<MediaContainerType> CheckVideoConfiguration(
+    const VideoConfiguration& aConfig) const;
+  Maybe<MediaContainerType> CheckAudioConfiguration(
+    const AudioConfiguration& aConfig) const;
+  bool CheckTypeForMediaSource(const nsAString& aType);
+  bool CheckTypeForFile(const nsAString& aType);
+  bool CheckTypeForEncoder(const nsAString& aType);
+  already_AddRefed<layers::KnowsCompositor> GetCompositor();
+  nsCOMPtr<nsIGlobalObject> mParent;
+};
+
+class MediaCapabilitiesInfo final : public NonRefcountedDOMObject
+{
+public:
+  // WebIDL methods
+  bool Supported() const { return mSupported; }
+  bool Smooth() const { return mSmooth; }
+  bool PowerEfficient() const { return mPowerEfficient; }
+  // End WebIDL methods
+
+  MediaCapabilitiesInfo(bool aSupported, bool aSmooth, bool aPowerEfficient)
+    : mSupported(aSupported)
+    , mSmooth(aSmooth)
+    , mPowerEfficient(aPowerEfficient)
+  {
+  }
+
+  bool WrapObject(JSContext* aCx,
+                  JS::Handle<JSObject*> aGivenProto,
+                  JS::MutableHandle<JSObject*> aReflector);
+
+private:
+  bool mSupported;
+  bool mSmooth;
+  bool mPowerEfficient;
+};
+
+} // namespace dom
+
+} // namespace mozilla
+
+#endif /* mozilla_dom_MediaCapabilities_h_ */
new file mode 100644
--- /dev/null
+++ b/dom/media/mediacapabilities/moz.build
@@ -0,0 +1,14 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+EXPORTS.mozilla.dom += [
+    'MediaCapabilities.h',
+]
+
+UNIFIED_SOURCES += [
+    'MediaCapabilities.cpp',
+]
+
+FINAL_LIBRARY = 'xul'
deleted file mode 100644
--- a/dom/media/mediasource/AutoTaskQueue.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef MOZILLA_AUTOTASKQUEUE_H_
-#define MOZILLA_AUTOTASKQUEUE_H_
-
-#include "mozilla/RefPtr.h"
-#include "mozilla/SystemGroup.h"
-#include "mozilla/TaskQueue.h"
-
-class nsIEventTarget;
-
-namespace mozilla {
-
-// A convenience TaskQueue not requiring explicit shutdown.
-class AutoTaskQueue : public AbstractThread
-{
-public:
-  explicit AutoTaskQueue(already_AddRefed<nsIEventTarget> aPool,
-                         bool aSupportsTailDispatch = false)
-    : AbstractThread(aSupportsTailDispatch)
-    , mTaskQueue(new TaskQueue(std::move(aPool), aSupportsTailDispatch))
-    , mMonitor("AutoTaskQueue")
-  {
-  }
-
-  AutoTaskQueue(already_AddRefed<nsIEventTarget> aPool,
-                const char* aName,
-                bool aSupportsTailDispatch = false)
-    : AbstractThread(aSupportsTailDispatch)
-    , mTaskQueue(new TaskQueue(std::move(aPool), aName, aSupportsTailDispatch))
-    , mMonitor("AutoTaskQueue")
-  {
-  }
-
-  TaskDispatcher& TailDispatcher() override
-  {
-    return mTaskQueue->TailDispatcher();
-  }
-
-  MOZ_MUST_USE nsresult
-  Dispatch(already_AddRefed<nsIRunnable> aRunnable,
-           DispatchReason aReason = NormalDispatch) override
-  {
-    return mTaskQueue->Dispatch(std::move(aRunnable), aReason);
-  }
-
-  // Prevent a GCC warning about the other overload of Dispatch being hidden.
-  using AbstractThread::Dispatch;
-
-  // Blocks until all tasks finish executing.
-  void AwaitIdle() { mTaskQueue->AwaitIdle(); }
-
-  bool IsEmpty() { return mTaskQueue->IsEmpty(); }
-
-  // Returns true if the current thread is currently running a Runnable in
-  // the task queue.
-  bool IsCurrentThreadIn() override { return mTaskQueue->IsCurrentThreadIn(); }
-
-  mozilla::Monitor& Monitor() { return mMonitor; }
-
-private:
-  ~AutoTaskQueue() { mTaskQueue->BeginShutdown(); }
-  RefPtr<TaskQueue> mTaskQueue;
-  mozilla::Monitor mMonitor;
-};
-
-} // namespace mozilla
-
-#endif
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -17,16 +17,17 @@
 #include "MediaResult.h"
 #include "MediaSourceDemuxer.h"
 #include "MediaSourceUtils.h"
 #include "SourceBuffer.h"
 #include "SourceBufferList.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/StaticPrefs.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/mozalloc.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsIRunnable.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsPIDOMWindow.h"
@@ -125,16 +126,17 @@ MediaSource::IsTypeSupported(const nsASt
       mimeType == MEDIAMIMETYPE("audio/mp4")) {
     if (!Preferences::GetBool("media.mediasource.mp4.enabled", false)) {
       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     }
     return NS_OK;
   }
   if (mimeType == MEDIAMIMETYPE("video/webm")) {
     if (!(Preferences::GetBool("media.mediasource.webm.enabled", false) ||
+          StaticPrefs::MediaCapabilitiesEnabled() ||
           containerType->ExtendedType().Codecs().Contains(
             NS_LITERAL_STRING("vp8")) ||
 #ifdef MOZ_AV1
           // FIXME: Temporary comparison with the full codecs attribute.
           // See bug 1377015.
           AOMDecoder::IsSupportedCodec(containerType->ExtendedType().Codecs().AsString()) ||
 #endif
           IsWebMForced(aDiagnostics))) {
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -19,18 +19,18 @@
 
 namespace mozilla {
 
 typedef TrackInfo::TrackType TrackType;
 using media::TimeUnit;
 using media::TimeIntervals;
 
 MediaSourceDemuxer::MediaSourceDemuxer(AbstractThread* aAbstractMainThread)
-  : mTaskQueue(new AutoTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
-                                 "MediaSourceDemuxer::mTaskQueue"))
+  : mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
+                             "MediaSourceDemuxer::mTaskQueue"))
   , mMonitor("MediaSourceDemuxer")
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 constexpr TimeUnit MediaSourceDemuxer::EOS_FUZZ;
 
 RefPtr<MediaSourceDemuxer::InitPromise>
--- a/dom/media/mediasource/MediaSourceDemuxer.h
+++ b/dom/media/mediasource/MediaSourceDemuxer.h
@@ -2,25 +2,25 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #if !defined(MediaSourceDemuxer_h_)
 #define MediaSourceDemuxer_h_
 
-#include "mozilla/Atomics.h"
-#include "mozilla/Maybe.h"
-#include "mozilla/Monitor.h"
-#include "AutoTaskQueue.h"
-
 #include "MediaDataDemuxer.h"
 #include "MediaResource.h"
 #include "MediaSource.h"
 #include "TrackBuffersManager.h"
+#include "mozilla/Atomics.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Monitor.h"
+#include "mozilla/TaskQueue.h"
+
 
 namespace mozilla {
 
 class AbstractThread;
 class MediaResult;
 class MediaSourceTrackDemuxer;
 
 DDLoggedTypeDeclNameAndBase(MediaSourceDemuxer, MediaDataDemuxer);
@@ -44,17 +44,17 @@ public:
 
   UniquePtr<EncryptionInfo> GetCrypto() override;
 
   bool ShouldComputeStartTime() const override { return false; }
 
   /* interface for TrackBuffersManager */
   void AttachSourceBuffer(RefPtr<TrackBuffersManager>& aSourceBuffer);
   void DetachSourceBuffer(RefPtr<TrackBuffersManager>& aSourceBuffer);
-  AutoTaskQueue* GetTaskQueue() { return mTaskQueue; }
+  TaskQueue* GetTaskQueue() { return mTaskQueue; }
   void NotifyInitDataArrived();
 
   // Returns a string describing the state of the MediaSource internal
   // buffered data. Used for debugging purposes.
   void GetMozDebugReaderData(nsACString& aString);
 
   void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes);
 
@@ -73,17 +73,17 @@ private:
   TrackInfo* GetTrackInfo(TrackInfo::TrackType);
   void DoAttachSourceBuffer(RefPtr<TrackBuffersManager>&& aSourceBuffer);
   void DoDetachSourceBuffer(RefPtr<TrackBuffersManager>&& aSourceBuffer);
   bool OnTaskQueue()
   {
     return !GetTaskQueue() || GetTaskQueue()->IsCurrentThreadIn();
   }
 
-  RefPtr<AutoTaskQueue> mTaskQueue;
+  RefPtr<TaskQueue> mTaskQueue;
   nsTArray<RefPtr<MediaSourceTrackDemuxer>> mDemuxers;
 
   nsTArray<RefPtr<TrackBuffersManager>> mSourceBuffers;
 
   MozPromiseHolder<InitPromise> mInitPromise;
 
   // Monitor to protect members below across multiple threads.
   mutable Monitor mMonitor;
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -172,17 +172,17 @@ TrackBuffersManager::DoAppendData(alread
 }
 
 void
 TrackBuffersManager::QueueTask(SourceBufferTask* aTask)
 {
   // The source buffer is a wrapped native, it would be unlinked twice and so
   // the TrackBuffersManager::Detach() would also be called twice. Since the
   // detach task has been done before, we could ignore this task.
-  RefPtr<AutoTaskQueue> taskQueue = GetTaskQueueSafe();
+  RefPtr<TaskQueue> taskQueue = GetTaskQueueSafe();
   if (!taskQueue) {
     MOZ_ASSERT(aTask->GetType() == SourceBufferTask::Type::Detach,
                "only detach task could happen here!");
     MSE_DEBUG("Could not queue the task '%s' without task queue",
               aTask->GetTypeName());
     return;
   }
 
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -6,17 +6,17 @@
 
 #ifndef MOZILLA_TRACKBUFFERSMANAGER_H_
 #define MOZILLA_TRACKBUFFERSMANAGER_H_
 
 #include "mozilla/Atomics.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/NotNull.h"
-#include "AutoTaskQueue.h"
+#include "mozilla/TaskQueue.h"
 
 #include "MediaContainerType.h"
 #include "MediaData.h"
 #include "MediaDataDemuxer.h"
 #include "MediaResult.h"
 #include "MediaSourceDecoder.h"
 #include "SourceBufferTask.h"
 #include "TimeUnits.h"
@@ -460,25 +460,25 @@ private:
       default:
         return mAudioTracks;
     }
   }
   TrackData mVideoTracks;
   TrackData mAudioTracks;
 
   // TaskQueue methods and objects.
-  RefPtr<AutoTaskQueue> GetTaskQueueSafe() const
+  RefPtr<TaskQueue> GetTaskQueueSafe() const
   {
     MutexAutoLock mut(mMutex);
     return mTaskQueue;
   }
   NotNull<AbstractThread*> TaskQueueFromTaskQueue() const
   {
 #ifdef DEBUG
-    RefPtr<AutoTaskQueue> taskQueue = GetTaskQueueSafe();
+    RefPtr<TaskQueue> taskQueue = GetTaskQueueSafe();
     MOZ_ASSERT(taskQueue && taskQueue->IsCurrentThreadIn());
 #endif
     return WrapNotNull(mTaskQueue.get());
   }
   bool OnTaskQueue() const
   {
     auto taskQueue = TaskQueueFromTaskQueue();
     return taskQueue->IsCurrentThreadIn();
@@ -528,17 +528,17 @@ private:
   };
   Atomic<EvictionState> mEvictionState;
 
   // Monitor to protect following objects accessed across multiple threads.
   mutable Mutex mMutex;
   // mTaskQueue is only ever written after construction on the task queue.
   // As such, it can be accessed while on task queue without the need for the
   // mutex.
-  RefPtr<AutoTaskQueue> mTaskQueue;
+  RefPtr<TaskQueue> mTaskQueue;
   // Stable audio and video track time ranges.
   media::TimeIntervals mVideoBufferedRanges;
   media::TimeIntervals mAudioBufferedRanges;
   // MediaInfo of the first init segment read.
   MediaInfo mInfo;
 };
 
 } // namespace mozilla
--- a/dom/media/mediasource/moz.build
+++ b/dom/media/mediasource/moz.build
@@ -2,17 +2,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 EXPORTS += [
     'AsyncEventRunner.h',
-    'AutoTaskQueue.h',
     'MediaSourceDecoder.h',
     'MediaSourceDemuxer.h',
     'SourceBufferAttributes.h',
     'SourceBufferTask.h',
     'TrackBuffersManager.h',
 ]
 
 EXPORTS.mozilla.dom += [
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -36,16 +36,17 @@ DIRS += [
     'eme',
     'encoder',
     'fake-cdm',
     'flac',
     'gmp',
     'gmp-plugin-openh264',
     'imagecapture',
     'ipc',
+    'mediacapabilities',
     'mediasink',
     'mediasource',
     'mp3',
     'ogg',
     'platforms',
     'systemservices',
     'wave',
     'webaudio',
@@ -99,16 +100,17 @@ EXPORTS += [
     'AudioPacketizer.h',
     'AudioSampleFormat.h',
     'AudioSegment.h',
     'AudioStream.h',
     'AutoplayPolicy.h',
     'BackgroundVideoDecodingPermissionObserver.h',
     'Benchmark.h',
     'BitReader.h',
+    'BitWriter.h',
     'BufferMediaResource.h',
     'BufferReader.h',
     'ByteWriter.h',
     'ChannelMediaDecoder.h',
     'CubebUtils.h',
     'DecoderTraits.h',
     'DOMMediaStream.h',
     'FileBlockCache.h',
@@ -218,16 +220,17 @@ UNIFIED_SOURCES += [
     'AudioStreamTrack.cpp',
     'AudioTrack.cpp',
     'AudioTrackList.cpp',
     'AutoplayPolicy.cpp',
     'BackgroundVideoDecodingPermissionObserver.cpp',
     'BaseMediaResource.cpp',
     'Benchmark.cpp',
     'BitReader.cpp',
+    'BitWriter.cpp',
     'CanvasCaptureMediaStream.cpp',
     'ChannelMediaDecoder.cpp',
     'ChannelMediaResource.cpp',
     'CloneableWithRangeMediaResource.cpp',
     'DOMMediaStream.cpp',
     'FileBlockCache.cpp',
     'FileMediaResource.cpp',
     'GetUserMediaRequest.cpp',
--- a/dom/media/mp3/MP3Decoder.cpp
+++ b/dom/media/mp3/MP3Decoder.cpp
@@ -24,9 +24,24 @@ bool MP3Decoder::IsSupportedType(const M
   if (aContainerType.Type() == MEDIAMIMETYPE("audio/mp3") ||
       aContainerType.Type() == MEDIAMIMETYPE("audio/mpeg")) {
     return IsEnabled() && (aContainerType.ExtendedType().Codecs().IsEmpty() ||
                            aContainerType.ExtendedType().Codecs() == "mp3");
   }
   return false;
 }
 
+/* static */ nsTArray<UniquePtr<TrackInfo>>
+MP3Decoder::GetTracksInfo(const MediaContainerType& aType)
+{
+  nsTArray<UniquePtr<TrackInfo>> tracks;
+  if (!IsSupportedType(aType)) {
+    return tracks;
+  }
+
+  tracks.AppendElement(
+    CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+      NS_LITERAL_CSTRING("audio/mpeg"), aType));
+
+  return tracks;
+}
+
 } // namespace mozilla
--- a/dom/media/mp3/MP3Decoder.h
+++ b/dom/media/mp3/MP3Decoder.h
@@ -1,24 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef MP3Decoder_h_
 #define MP3Decoder_h_
 
+#include "mozilla/UniquePtr.h"
+#include "nsTArray.h"
+
 namespace mozilla {
 
 class MediaContainerType;
+class TrackInfo;
 
 class MP3Decoder
 {
 public:
   // Returns true if the MP3 backend is preffed on, and we're running on a
   // platform that is likely to have decoders for the format.
   static bool IsEnabled();
   static bool IsSupportedType(const MediaContainerType& aContainerType);
+  static nsTArray<UniquePtr<TrackInfo>> GetTracksInfo(
+    const MediaContainerType& aType);
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/mp4/MP4Decoder.cpp
+++ b/dom/media/mp4/MP4Decoder.cpp
@@ -1,30 +1,31 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MP4Decoder.h"
+#include "H264.h"
+#include "MP4Demuxer.h"
 #include "MediaContainerType.h"
-#include "MP4Demuxer.h"
+#include "PDMFactory.h"
+#include "VideoUtils.h"
+#include "mozilla/StaticPrefs.h"
 #include "nsMimeTypes.h"
-#include "VideoUtils.h"
-#include "PDMFactory.h"
-#include "mozilla/StaticPrefs.h"
 
 namespace mozilla {
 
 static bool
 IsWhitelistedH264Codec(const nsAString& aCodec)
 {
-  int16_t profile = 0, level = 0;
+  uint8_t profile = 0, constraint = 0, level = 0;
 
-  if (!ExtractH264CodecDetails(aCodec, profile, level)) {
+  if (!ExtractH264CodecDetails(aCodec, profile, constraint, level)) {
     return false;
   }
 
   // Just assume what we can play on all platforms the codecs/formats that
   // WMF can play, since we don't have documentation about what other
   // platforms can play... According to the WMF documentation:
   // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815%28v=vs.85%29.aspx
   // "The Media Foundation H.264 video decoder is a Media Foundation Transform
@@ -44,109 +45,139 @@ IsWhitelistedH264Codec(const nsAString& 
 /* static */
 bool
 MP4Decoder::IsSupportedTypeWithoutDiagnostics(
   const MediaContainerType& aContainerType)
 {
   return IsSupportedType(aContainerType, nullptr);
 }
 
+static bool IsTypeValid(const MediaContainerType& aType)
+{
+  // Whitelist MP4 types, so they explicitly match what we encounter on
+  // the web, as opposed to what we use internally (i.e. what our demuxers
+  // etc output).
+  return aType.Type() == MEDIAMIMETYPE("audio/mp4") ||
+         aType.Type() == MEDIAMIMETYPE("audio/x-m4a") ||
+         aType.Type() == MEDIAMIMETYPE("video/mp4") ||
+         aType.Type() == MEDIAMIMETYPE("video/quicktime") ||
+         aType.Type() == MEDIAMIMETYPE("video/x-m4v");
+}
+
+/* statis */ nsTArray<UniquePtr<TrackInfo>>
+MP4Decoder::GetTracksInfo(const MediaContainerType& aType, MediaResult& aError)
+{
+  nsTArray<UniquePtr<TrackInfo>> tracks;
+
+  if (!IsTypeValid(aType)) {
+    aError = MediaResult(
+      NS_ERROR_DOM_MEDIA_FATAL_ERR,
+      RESULT_DETAIL("Invalid type:%s", aType.Type().AsString().get()));
+    return tracks;
+  }
+
+  aError = NS_OK;
+
+  const MediaCodecs& codecs = aType.ExtendedType().Codecs();
+  if (codecs.IsEmpty()) {
+    return tracks;
+  }
+
+  const bool isVideo = aType.Type() == MEDIAMIMETYPE("video/mp4") ||
+                       aType.Type() == MEDIAMIMETYPE("video/quicktime") ||
+                       aType.Type() == MEDIAMIMETYPE("video/x-m4v");
+
+  for (const auto& codec : codecs.Range()) {
+    if (IsAACCodecString(codec)) {
+      tracks.AppendElement(
+        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+          NS_LITERAL_CSTRING("audio/mp4a-latm"), aType));
+      continue;
+    }
+    if (codec.EqualsLiteral("mp3")) {
+      tracks.AppendElement(
+        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+          NS_LITERAL_CSTRING("audio/mpeg"), aType));
+      continue;
+    }
+    if (codec.EqualsLiteral("opus") || codec.EqualsLiteral("flac")) {
+      tracks.AppendElement(
+        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+          NS_LITERAL_CSTRING("audio/") + NS_ConvertUTF16toUTF8(codec), aType));
+      continue;
+    }
+    if (IsVP9CodecString(codec)) {
+      auto trackInfo =
+        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+          NS_LITERAL_CSTRING("video/vp9"), aType);
+      uint8_t profile = 0;
+      uint8_t level = 0;
+      uint8_t bitDepth = 0;
+      if (ExtractVPXCodecDetails(codec, profile, level, bitDepth)) {
+        trackInfo->GetAsVideoInfo()->mBitDepth = bitDepth;
+      }
+      tracks.AppendElement(std::move(trackInfo));
+      continue;
+    }
+    if (isVideo && IsWhitelistedH264Codec(codec)) {
+      auto trackInfo =
+        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+          NS_LITERAL_CSTRING("video/avc"), aType);
+      uint8_t profile = 0, constraint = 0, level = 0;
+      MOZ_ALWAYS_TRUE(
+        ExtractH264CodecDetails(codec, profile, constraint, level));
+      uint32_t width = aType.ExtendedType().GetWidth().refOr(1280);
+      uint32_t height = aType.ExtendedType().GetHeight().refOr(720);
+      trackInfo->GetAsVideoInfo()->mExtraData =
+        H264::CreateExtraData(profile, constraint, level, { width, height });
+      tracks.AppendElement(std::move(trackInfo));
+      continue;
+    }
+    // Unknown codec
+    aError =
+      MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+                  RESULT_DETAIL("Unknown codec:%s",
+                                NS_ConvertUTF16toUTF8(codec).get()));
+  }
+  return tracks;
+}
+
 /* static */
 bool
 MP4Decoder::IsSupportedType(const MediaContainerType& aType,
                             DecoderDoctorDiagnostics* aDiagnostics)
 {
   if (!IsEnabled()) {
     return false;
   }
 
-  // Whitelist MP4 types, so they explicitly match what we encounter on
-  // the web, as opposed to what we use internally (i.e. what our demuxers
-  // etc output).
-  const bool isAudio = aType.Type() == MEDIAMIMETYPE("audio/mp4") ||
-                       aType.Type() == MEDIAMIMETYPE("audio/x-m4a");
-  const bool isVideo = aType.Type() == MEDIAMIMETYPE("video/mp4") ||
-                       aType.Type() == MEDIAMIMETYPE("video/quicktime") ||
-                       aType.Type() == MEDIAMIMETYPE("video/x-m4v");
-
-  if (!isAudio && !isVideo) {
+  MediaResult rv = NS_OK;
+  auto tracks = GetTracksInfo(aType, rv);
+  if (NS_FAILED(rv)) {
     return false;
   }
 
-  nsTArray<UniquePtr<TrackInfo>> trackInfos;
-  if (aType.ExtendedType().Codecs().IsEmpty()) {
-    // No codecs specified. Assume H.264
-    if (isAudio) {
-      trackInfos.AppendElement(
+  if (tracks.IsEmpty()) {
+    // No codecs specified. Assume H.264 or AAC
+    if (aType.Type() == MEDIAMIMETYPE("audio/mp4") ||
+        aType.Type() == MEDIAMIMETYPE("audio/x-m4a")) {
+      tracks.AppendElement(
         CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
           NS_LITERAL_CSTRING("audio/mp4a-latm"), aType));
     } else {
-      MOZ_ASSERT(isVideo);
-      trackInfos.AppendElement(
+      tracks.AppendElement(
         CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
           NS_LITERAL_CSTRING("video/avc"), aType));
     }
-  } else {
-    // Verify that all the codecs specified are ones that we expect that
-    // we can play.
-    for (const auto& codec : aType.ExtendedType().Codecs().Range()) {
-      if (IsAACCodecString(codec)) {
-        trackInfos.AppendElement(
-          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
-            NS_LITERAL_CSTRING("audio/mp4a-latm"), aType));
-        continue;
-      }
-      if (codec.EqualsLiteral("mp3")) {
-        trackInfos.AppendElement(
-          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
-            NS_LITERAL_CSTRING("audio/mpeg"), aType));
-        continue;
-      }
-      if (codec.EqualsLiteral("opus")) {
-        trackInfos.AppendElement(
-          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
-            NS_LITERAL_CSTRING("audio/opus"), aType));
-        continue;
-      }
-      if (codec.EqualsLiteral("flac")) {
-        trackInfos.AppendElement(
-          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
-            NS_LITERAL_CSTRING("audio/flac"), aType));
-        continue;
-      }
-      if (IsVP9CodecString(codec)) {
-        auto trackInfo =
-          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
-            NS_LITERAL_CSTRING("video/vp9"), aType);
-        uint8_t profile = 0;
-        uint8_t level = 0;
-        uint8_t bitDepth = 0;
-        if (ExtractVPXCodecDetails(codec, profile, level, bitDepth)) {
-          trackInfo->GetAsVideoInfo()->mBitDepth = bitDepth;
-        }
-        trackInfos.AppendElement(std::move(trackInfo));
-        continue;
-      }
-      // Note: Only accept H.264 in a video content type, not in an audio
-      // content type.
-      if (IsWhitelistedH264Codec(codec) && isVideo) {
-        trackInfos.AppendElement(
-          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
-            NS_LITERAL_CSTRING("video/avc"), aType));
-        continue;
-      }
-      // Some unsupported codec.
-      return false;
-    }
   }
 
   // Verify that we have a PDM that supports the whitelisted types.
   RefPtr<PDMFactory> platform = new PDMFactory();
-  for (const auto& trackInfo : trackInfos) {
-    if (!trackInfo || !platform->Supports(*trackInfo, aDiagnostics)) {
+  for (const auto& track : tracks) {
+    if (!track || !platform->Supports(*track, aDiagnostics)) {
       return false;
     }
   }
 
   return true;
 }
 
 /* static */
@@ -166,9 +197,16 @@ MP4Decoder::IsAAC(const nsACString& aMim
 
 /* static */
 bool
 MP4Decoder::IsEnabled()
 {
   return StaticPrefs::mediaMp4Enabled();
 }
 
+/* static */ nsTArray<UniquePtr<TrackInfo>>
+MP4Decoder::GetTracksInfo(const MediaContainerType& aType)
+{
+  MediaResult rv = NS_OK;
+  return GetTracksInfo(aType, rv);
+}
+
 } // namespace mozilla
--- a/dom/media/mp4/MP4Decoder.h
+++ b/dom/media/mp4/MP4Decoder.h
@@ -1,22 +1,25 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(MP4Decoder_h_)
 #define MP4Decoder_h_
 
+#include "mozilla/UniquePtr.h"
 #include "nsStringFwd.h"
+#include "nsTArray.h"
 
 namespace mozilla {
 
 class MediaContainerType;
 class DecoderDoctorDiagnostics;
+class TrackInfo;
 
 // Decoder that uses a bundled MP4 demuxer and platform decoders to play MP4.
 class MP4Decoder
 {
 public:
   // Returns true if aContainerType is an MP4 type that we think we can render
   // with the a platform decoder backend.
   // If provided, codecs are checked for support.
@@ -34,13 +37,20 @@ public:
   // Return true if aMimeType is a one of the strings used by our demuxers to
   // identify AAC. Does not parse general content type strings, i.e. white
   // space matters.
   static bool IsAAC(const nsACString& aMimeType);
 
   // Returns true if the MP4 backend is preffed on.
   static bool IsEnabled();
 
+  static nsTArray<UniquePtr<TrackInfo>> GetTracksInfo(
+    const MediaContainerType& aType);
+
+private:
+  static nsTArray<UniquePtr<TrackInfo>> GetTracksInfo(
+    const MediaContainerType& aType,
+    MediaResult& aError);
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/mp4/MoofParser.cpp
+++ b/dom/media/mp4/MoofParser.cpp
@@ -48,17 +48,16 @@ MoofParser::RebuildFragmentedIndex(
   }
   return RebuildFragmentedIndex(aByteRanges);
 }
 
 bool
 MoofParser::RebuildFragmentedIndex(BoxContext& aContext)
 {
   bool foundValidMoof = false;
-  bool foundMdat = false;
 
   for (Box box(&aContext, mOffset); box.IsAvailable(); box = box.Next()) {
     if (box.IsType("moov") && mInitRange.IsEmpty()) {
       mInitRange = MediaByteRange(0, box.Range().mEnd);
       ParseMoov(box);
     } else if (box.IsType("moof")) {
       Moof moof(box, mTrex, mMvhd, mMdhd, mEdts, mSinf, &mLastDecodeTime, mIsAudio);
 
@@ -601,17 +600,16 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, 
 
   BoxReader reader(aBox);
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Moof, "Incomplete Box (missing flags)");
     return Err(NS_ERROR_FAILURE);
   }
   uint32_t flags;
   MOZ_TRY_VAR(flags, reader->ReadU32());
-  uint8_t version = flags >> 24;
 
   if (!reader->CanReadType<uint32_t>()) {
     LOG(Moof, "Incomplete Box (missing sampleCount)");
     return Err(NS_ERROR_FAILURE);
   }
   uint32_t sampleCount;
   MOZ_TRY_VAR(sampleCount, reader->ReadU32());
   if (sampleCount == 0) {
--- a/dom/media/ogg/OggDecoder.cpp
+++ b/dom/media/ogg/OggDecoder.cpp
@@ -25,32 +25,61 @@ OggDecoder::IsSupportedType(const MediaC
       aContainerType.Type() != MEDIAMIMETYPE("application/ogg")) {
     return false;
   }
 
   const bool isOggVideo = (aContainerType.Type() != MEDIAMIMETYPE(AUDIO_OGG));
 
   const MediaCodecs& codecs = aContainerType.ExtendedType().Codecs();
   if (codecs.IsEmpty()) {
-    // WebM guarantees that the only codecs it contained are vp8, vp9, opus or vorbis.
+    // Ogg guarantees that the only codecs it contained are supported.
     return true;
   }
   // Verify that all the codecs specified are ones that we expect that
   // we can play.
   for (const auto& codec : codecs.Range()) {
     if ((MediaDecoder::IsOpusEnabled() && codec.EqualsLiteral("opus")) ||
         codec.EqualsLiteral("vorbis") ||
-        (StaticPrefs::MediaOggFlacEnabled() &&
-         codec.EqualsLiteral("flac"))) {
+        codec.EqualsLiteral("flac")) {
       continue;
     }
     // Note: Only accept Theora in a video container type, not in an audio
     // container type.
     if (isOggVideo && codec.EqualsLiteral("theora")) {
       continue;
     }
     // Some unsupported codec.
     return false;
   }
   return true;
 }
 
+/* static */ nsTArray<UniquePtr<TrackInfo>>
+OggDecoder::GetTracksInfo(const MediaContainerType& aType)
+{
+  nsTArray<UniquePtr<TrackInfo>> tracks;
+  if (!IsSupportedType(aType)) {
+    return tracks;
+  }
+
+  const MediaCodecs& codecs = aType.ExtendedType().Codecs();
+  if (codecs.IsEmpty()) {
+    // Codecs must be specified for ogg as it can't be implied.
+    return tracks;
+  }
+
+  for (const auto& codec : codecs.Range()) {
+    if (codec.EqualsLiteral("opus") || codec.EqualsLiteral("vorbis") ||
+        codec.EqualsLiteral("flac")) {
+      tracks.AppendElement(
+        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+          NS_LITERAL_CSTRING("audio/") + NS_ConvertUTF16toUTF8(codec), aType));
+    } else {
+      MOZ_ASSERT(codec.EqualsLiteral("theora"));
+      tracks.AppendElement(
+        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+          NS_LITERAL_CSTRING("video/") + NS_ConvertUTF16toUTF8(codec), aType));
+    }
+  }
+  return tracks;
+}
+
 } // namespace mozilla
--- a/dom/media/ogg/OggDecoder.h
+++ b/dom/media/ogg/OggDecoder.h
@@ -1,24 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(OggDecoder_h_)
 #define OggDecoder_h_
 
+#include "mozilla/UniquePtr.h"
+#include "nsTArray.h"
+
 namespace mozilla {
 
 class MediaContainerType;
+class TrackInfo;
 
 class OggDecoder
 {
 public:
   // Returns true if aContainerType is an Ogg type that we think we can render
   // with an enabled platform decoder backend.
   // If provided, codecs are checked for support.
   static bool IsSupportedType(const MediaContainerType& aContainerType);
+  static nsTArray<UniquePtr<TrackInfo>> GetTracksInfo(
+    const MediaContainerType& aType);
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/ogg/OggDemuxer.cpp
+++ b/dom/media/ogg/OggDemuxer.cpp
@@ -533,18 +533,17 @@ OggDemuxer::ReadMetadata()
             SetupTarget(&mOpusState, s);
           } else {
             s->Deactivate();
           }
         } else {
           NS_WARNING("Opus decoding disabled."
                      " See media.opus.enabled in about:config");
         }
-      } else if (StaticPrefs::MediaOggFlacEnabled() &&
-                 s->GetType() == OggCodecState::TYPE_FLAC &&
+      } else if (s->GetType() == OggCodecState::TYPE_FLAC &&
                  ReadHeaders(TrackInfo::kAudioTrack, s)) {
         if (!mFlacState) {
           SetupTarget(&mFlacState, s);
         } else {
           s->Deactivate();
         }
       } else if (s->GetType() == OggCodecState::TYPE_SKELETON && !mSkeletonState) {
         mSkeletonState = static_cast<SkeletonState*>(s);
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -289,17 +289,18 @@ PDMFactory::CreateDecoderWithPDM(Platfor
 
   if (!config.IsVideo()) {
     *result = MediaResult(
       NS_ERROR_DOM_MEDIA_FATAL_ERR,
       RESULT_DETAIL("Decoder configuration error, expected audio or video."));
     return nullptr;
   }
 
-  if (MP4Decoder::IsH264(config.mMimeType) && !aParams.mUseNullDecoder.mUse) {
+  if (MP4Decoder::IsH264(config.mMimeType) && !aParams.mUseNullDecoder.mUse &&
+      !aParams.mNoWrapper.mDontUseWrapper) {
     RefPtr<H264Converter> h = new H264Converter(aPDM, aParams);
     const MediaResult result = h->GetLastError();
     if (NS_SUCCEEDED(result) || result == NS_ERROR_NOT_INITIALIZED) {
       // The H264Converter either successfully created the wrapped decoder,
       // or there wasn't enough AVCC data to do so. Otherwise, there was some
       // problem, for example WMF DLLs were missing.
       m = h.forget();
     } else if (aParams.mError) {
--- a/dom/media/platforms/PlatformDecoderModule.h
+++ b/dom/media/platforms/PlatformDecoderModule.h
@@ -55,16 +55,27 @@ struct MOZ_STACK_CLASS CreateDecoderPara
 
   struct UseNullDecoder
   {
     UseNullDecoder() = default;
     explicit UseNullDecoder(bool aUseNullDecoder) : mUse(aUseNullDecoder) { }
     bool mUse = false;
   };
 
+  // Do not wrap H264 decoder in a H264Converter.
+  struct NoWrapper
+  {
+    NoWrapper() = default;
+    explicit NoWrapper(bool aDontUseWrapper)
+      : mDontUseWrapper(aDontUseWrapper)
+    {
+    }
+    bool mDontUseWrapper = false;
+  };
+
   struct VideoFrameRate
   {
     VideoFrameRate() = default;
     explicit VideoFrameRate(float aFramerate) : mValue(aFramerate) { }
     float mValue = 0.0f;
   };
 
   template <typename T1, typename... Ts>
@@ -97,16 +108,17 @@ struct MOZ_STACK_CLASS CreateDecoderPara
   const TrackInfo& mConfig;
   TaskQueue* mTaskQueue = nullptr;
   DecoderDoctorDiagnostics* mDiagnostics = nullptr;
   layers::ImageContainer* mImageContainer = nullptr;
   MediaResult* mError = nullptr;
   RefPtr<layers::KnowsCompositor> mKnowsCompositor;
   RefPtr<GMPCrashHelper> mCrashHelper;
   UseNullDecoder mUseNullDecoder;
+  NoWrapper mNoWrapper;
   TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack;
   MediaEventProducer<TrackInfo::TrackType>* mOnWaitingForKeyEvent = nullptr;
   OptionSet mOptions = OptionSet(Option::Default);
   VideoFrameRate mRate;
 
 private:
   void Set(TaskQueue* aTaskQueue) { mTaskQueue = aTaskQueue; }
   void Set(DecoderDoctorDiagnostics* aDiagnostics)
@@ -115,16 +127,17 @@ private:
   }
   void Set(layers::ImageContainer* aImageContainer)
   {
     mImageContainer = aImageContainer;
   }
   void Set(MediaResult* aError) { mError = aError; }
   void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; }
   void Set(UseNullDecoder aUseNullDecoder) { mUseNullDecoder = aUseNullDecoder; }
+  void Set(NoWrapper aNoWrapper) { mNoWrapper = aNoWrapper; }
   void Set(OptionSet aOptions) { mOptions = aOptions; }
   void Set(VideoFrameRate aRate) { mRate = aRate; }
   void Set(layers::KnowsCompositor* aKnowsCompositor)
   {
     if (aKnowsCompositor) {
       mKnowsCompositor = aKnowsCompositor;
       MOZ_ASSERT(aKnowsCompositor->IsThreadSafe());
     }
--- a/dom/media/platforms/agnostic/bytestreams/H264.cpp
+++ b/dom/media/platforms/agnostic/bytestreams/H264.cpp
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/ResultExtensions.h"
 #include "BitReader.h"
+#include "BitWriter.h"
 #include "BufferReader.h"
 #include "ByteWriter.h"
 #include "AnnexB.h"
 #include "H264.h"
 #include <limits>
 #include <cmath>
 
 #define READSE(var, min, max)                                                  \
@@ -115,62 +116,16 @@ scaling_list(BitReader& aBr, uint8_t (&a
 
 template <size_t N>
 static void
 scaling_list(BitReader& aBr, uint8_t (&aScalingList)[N], const uint8_t (&aDefaultList)[N])
 {
   detail::scaling_list(aBr, aScalingList, N, aDefaultList, nullptr);
 }
 
-static uint32_t
-GetBitLength(const mozilla::MediaByteBuffer* aNAL)
-{
-  size_t size = aNAL->Length();
-
-  while (size > 0 && aNAL->ElementAt(size - 1) == 0) {
-    size--;
-  }
-
-  if (!size) {
-    return 0;
-  }
-
-  if (size > UINT32_MAX / 8) {
-    // We can't represent it, we'll use as much as we can.
-    return UINT32_MAX;
-  }
-
-  uint8_t v = aNAL->ElementAt(size - 1);
-  size *= 8;
-
-  // Remove the stop bit and following trailing zeros.
-  if (v) {
-    // Count the consecutive zero bits (trailing) on the right by binary search.
-    // Adapted from Matt Whitlock algorithm to only bother with 8 bits integers.
-    uint32_t c;
-    if (v & 1) {
-      // Special case for odd v (assumed to happen half of the time).
-      c = 0;
-    } else {
-      c = 1;
-      if ((v & 0xf) == 0) {
-        v >>= 4;
-        c += 4;
-      }
-      if ((v & 0x3) == 0) {
-        v >>= 2;
-        c += 2;
-      }
-      c -= v & 0x1;
-    }
-    size -= c + 1;
-  }
-  return size;
-}
-
 SPSData::SPSData()
 {
   PodZero(this);
   // Default values when they aren't defined as per ITU-T H.264 (2014/02).
   chroma_format_idc = 1;
   video_format = 5;
   colour_primaries = 2;
   transfer_characteristics = 2;
@@ -200,17 +155,17 @@ public:
   {
     MOZ_ASSERT(aPtr);
 
     if (aLength == 0 || (*aPtr & 0x1f) != H264_NAL_SPS) {
       return;
     }
     mDecodedNAL = H264::DecodeNALUnit(aPtr, aLength);
     if (mDecodedNAL) {
-      mLength = GetBitLength(mDecodedNAL);
+      mLength = BitReader::GetBitLength(mDecodedNAL);
     }
   }
 
   SPSNAL() { }
 
   bool IsValid() const { return mDecodedNAL; }
 
   bool operator==(const SPSNAL& aOther) const
@@ -385,32 +340,66 @@ H264::DecodeNALUnit(const uint8_t* aNAL,
     } else {
       rbsp->AppendElement(byte);
     }
     lastbytes = (lastbytes << 8) | byte;
   }
   return rbsp.forget();
 }
 
+// The reverse of DecodeNALUnit. To allow the distinction between Annex B (that
+// uses 0x000001 as marker) and AVCC, the pattern 0x00 0x00 0x0n (where n is
+// between 0 and 3) can't be found in the bytestream. A 0x03 byte is inserted
+// after the second 0. Eg. 0x00 0x00 0x00 becomes 0x00 0x00 0x03 0x00
+/* static */ already_AddRefed<mozilla::MediaByteBuffer>
+H264::EncodeNALUnit(const uint8_t* aNAL, size_t aLength)
+{
+  MOZ_ASSERT(aNAL);
+  RefPtr<MediaByteBuffer> rbsp = new MediaByteBuffer();
+  BufferReader reader(aNAL, aLength);
+
+  auto res = reader.ReadU8();
+  if (res.isErr()) {
+    return rbsp.forget();
+  }
+  rbsp->AppendElement(res.unwrap());
+
+  res = reader.ReadU8();
+  if (res.isErr()) {
+    return rbsp.forget();
+  }
+  rbsp->AppendElement(res.unwrap());
+
+  while((res = reader.ReadU8()).isOk()) {
+    uint8_t val = res.unwrap();
+    if (val <= 0x03 && rbsp->ElementAt(rbsp->Length() - 2) == 0 &&
+        rbsp->ElementAt(rbsp->Length() - 1) == 0) {
+      rbsp->AppendElement(0x03);
+    }
+    rbsp->AppendElement(val);
+  }
+  return rbsp.forget();
+}
+
 static int32_t
 ConditionDimension(float aValue)
 {
   // This will exclude NaNs and too-big values.
   if (aValue > 1.0 && aValue <= INT32_MAX)
     return int32_t(aValue);
   return 0;
 }
 
 /* static */ bool
 H264::DecodeSPS(const mozilla::MediaByteBuffer* aSPS, SPSData& aDest)
 {
   if (!aSPS) {
     return false;
   }
-  BitReader br(aSPS, GetBitLength(aSPS));
+  BitReader br(aSPS, BitReader::GetBitLength(aSPS));
 
   aDest.profile_idc = br.ReadBits(8);
   aDest.constraint_set0_flag = br.ReadBit();
   aDest.constraint_set1_flag = br.ReadBit();
   aDest.constraint_set2_flag = br.ReadBit();
   aDest.constraint_set3_flag = br.ReadBit();
   aDest.constraint_set4_flag = br.ReadBit();
   aDest.constraint_set5_flag = br.ReadBit();
@@ -1060,12 +1049,107 @@ H264::DecodeRecoverySEI(const mozilla::M
       aDest.changing_slice_group_idc = br.ReadBits(2);
       return true;
     }
   } while(br.PeekU8().isOk() && br.PeekU8().unwrap() != 0x80); // more_rbsp_data() msg[offset] != 0x80
   // ignore the trailing bits rbsp_trailing_bits();
   return false;
 }
 
+/*static */ already_AddRefed<mozilla::MediaByteBuffer>
+H264::CreateExtraData(uint8_t aProfile,
+                      uint8_t aConstraints,
+                      uint8_t aLevel,
+                      const gfx::IntSize& aSize)
+{
+  // SPS of a 144p video.
+  const uint8_t originSPS[] = { 0x4d, 0x40, 0x0c, 0xe8, 0x80, 0x80, 0x9d,
+                                0x80, 0xb5, 0x01, 0x01, 0x01, 0x40, 0x00,
+                                0x00, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
+                                0xc5, 0x0a, 0x44, 0x80 };
+
+  RefPtr<MediaByteBuffer> extraData = new MediaByteBuffer();
+  extraData->AppendElements(originSPS, sizeof(originSPS));
+  BitReader br(extraData, BitReader::GetBitLength(extraData));
+
+  RefPtr<MediaByteBuffer> sps = new MediaByteBuffer();
+  BitWriter bw(sps);
+
+  br.ReadBits(8); // Skip original profile_idc
+  bw.WriteU8(aProfile);
+  br.ReadBits(8); // Skip original constraint flags && reserved_zero_2bits
+  aConstraints = aConstraints & ~0x3; // Ensure reserved_zero_2bits are set to 0
+  bw.WriteBits(aConstraints, 8);
+  br.ReadBits(8); // Skip original level_idc
+  bw.WriteU8(aLevel);
+  bw.WriteUE(br.ReadUE()); // seq_parameter_set_id (0 stored on 1 bit)
+
+  if (aProfile == 100 || aProfile == 110 || aProfile == 122 ||
+      aProfile == 244 || aProfile == 44 || aProfile == 83 || aProfile == 86 ||
+      aProfile == 118 || aProfile == 128 || aProfile == 138 ||
+      aProfile == 139 || aProfile == 134) {
+    bw.WriteUE(1); // chroma_format_idc -> always set to 4:2:0 chroma format
+    bw.WriteUE(0); // bit_depth_luma_minus8 -> always 8 bits here
+    bw.WriteUE(0); // bit_depth_chroma_minus8 -> always 8 bits here
+  }
+
+  bw.WriteBits(br.ReadBits(11),
+               11); // log2_max_frame_num to gaps_in_frame_num_allowed_flag
+
+  // skip over original exp-golomb encoded width/height
+  br.ReadUE(); // skip width
+  br.ReadUE(); // skip height
+  uint32_t width = aSize.width;
+  uint32_t widthNeeded = width % 16 != 0 ? (width / 16 + 1) * 16 : width;
+  uint32_t height = aSize.height;
+  uint32_t heightNeeded = height % 16 != 0 ? (height / 16 + 1) * 16 : height;
+  bw.WriteUE(widthNeeded / 16 - 1);
+  bw.WriteUE(heightNeeded / 16 - 1);
+  bw.WriteBit(br.ReadBit()); // write frame_mbs_only_flag
+  bw.WriteBit(br.ReadBit()); // write direct_8x8_inference_flag;
+  if (widthNeeded != width || heightNeeded != height) {
+    // Write cropping value
+    bw.WriteBit(true);                       // skip frame_cropping_flag
+    bw.WriteUE(0);                           // frame_crop_left_offset
+    bw.WriteUE((widthNeeded - width) / 2);   // frame_crop_right_offset
+    bw.WriteUE(0);                           // frame_crop_top_offset
+    bw.WriteUE((heightNeeded - height) / 2); // frame_crop_bottom_offset
+  } else {
+    bw.WriteBit(false); // skip frame_cropping_flag
+  }
+  br.ReadBit(); // skip frame_cropping_flag;
+  // Write the remainings of the original sps (vui_parameters which sets an
+  // aspect ration of 1.0)
+  while (br.BitsLeft()) {
+    bw.WriteBit(br.ReadBit());
+  }
+  bw.CloseWithRbspTrailing();
+
+  RefPtr<MediaByteBuffer> encodedSPS =
+    EncodeNALUnit(sps->Elements(), sps->Length());
+  extraData->Clear();
+  extraData->AppendElement(1);
+  extraData->AppendElement(aProfile);
+  extraData->AppendElement(aConstraints);
+  extraData->AppendElement(aLevel);
+  extraData->AppendElement(3); // nalLENSize-1
+  extraData->AppendElement(1); // numPPS
+  uint8_t c[2];
+  mozilla::BigEndian::writeUint16(&c[0], encodedSPS->Length() + 1);
+  extraData->AppendElements(c, 2);
+  extraData->AppendElement((0x00 << 7) | (0x3 << 5 ) | H264_NAL_SPS);
+  extraData->AppendElements(*encodedSPS);
+
+  const uint8_t PPS[] = { 0xeb, 0xef, 0x20 };
+
+  extraData->AppendElement(1); // numPPS
+  mozilla::BigEndian::writeUint16(&c[0], sizeof(PPS) + 1);
+  extraData->AppendElements(c, 2);
+  extraData->AppendElement((0x00 << 7) | (0x3 << 5 ) | H264_NAL_PPS);
+  extraData->AppendElements(PPS, sizeof(PPS));
+
+  return extraData.forget();
+}
+
 #undef READUE
 #undef READSE
 
 } // namespace mozilla
--- a/dom/media/platforms/agnostic/bytestreams/H264.h
+++ b/dom/media/platforms/agnostic/bytestreams/H264.h
@@ -468,25 +468,34 @@ public:
     I_FRAME,
     OTHER,
     INVALID,
   };
 
   // Returns the frame type. Returns I_FRAME if the sample is an IDR
   // (Instantaneous Decoding Refresh) Picture.
   static FrameType GetFrameType(const mozilla::MediaRawData* aSample);
+  // Create a dummy extradata, useful to create a decoder and test the
+  // capabilities of the decoder.
+  static already_AddRefed<mozilla::MediaByteBuffer> CreateExtraData(
+    uint8_t aProfile,
+    uint8_t aConstraints,
+    uint8_t aLevel,
+    const gfx::IntSize& aSize);
 
 private:
   friend class SPSNAL;
   /* Extract RAW BYTE SEQUENCE PAYLOAD from NAL content.
      Returns nullptr if invalid content.
      This is compliant to ITU H.264 7.3.1 Syntax in tabular form NAL unit syntax
    */
   static already_AddRefed<mozilla::MediaByteBuffer> DecodeNALUnit(
     const uint8_t* aNAL, size_t aLength);
+  static already_AddRefed<mozilla::MediaByteBuffer> EncodeNALUnit(
+    const uint8_t* aNAL, size_t aLength);
   /* Decode SPS NAL RBSP and fill SPSData structure */
   static bool DecodeSPS(const mozilla::MediaByteBuffer* aSPS, SPSData& aDest);
   static bool vui_parameters(mozilla::BitReader& aBr, SPSData& aDest);
   // Read HRD parameters, all data is ignored.
   static void hrd_parameters(mozilla::BitReader& aBr);
   static uint8_t NumSPS(const mozilla::MediaByteBuffer* aExtraData);
   // Decode SEI payload and return true if the SEI NAL indicates a recovery
   // point.
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -647,17 +647,17 @@ private:
   RefPtr<MFTDecoder> mTransform;
   RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
   RefPtr<ID3D11VideoDecoder> mDecoder;
   RefPtr<layers::SyncObjectClient> mSyncObject;
   GUID mDecoderGUID;
   uint32_t mWidth = 0;
   uint32_t mHeight = 0;
   UINT mDeviceManagerToken = 0;
-  bool mConfiuredForSize = false;
+  bool mConfiguredForSize = false;
 };
 
 bool
 D3D11DXVA2Manager::SupportsConfig(IMFMediaType* aType, float aFramerate)
 {
   MOZ_ASSERT(NS_IsMainThread());
   D3D11_VIDEO_DECODER_DESC desc;
   desc.Guid = mDecoderGUID;
@@ -1087,17 +1087,17 @@ HRESULT ConfigureOutput(IMFMediaType* aO
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   return S_OK;
 }
 
 HRESULT
 D3D11DXVA2Manager::ConfigureForSize(uint32_t aWidth, uint32_t aHeight)
 {
-  if (mConfiuredForSize && aWidth == mWidth && aHeight == mHeight) {
+  if (mConfiguredForSize && aWidth == mWidth && aHeight == mHeight) {
     // If the size hasn't changed, don't reconfigure.
     return S_OK;
   }
 
   mWidth = aWidth;
   mHeight = aHeight;
 
   RefPtr<IMFMediaType> inputType;
@@ -1143,17 +1143,17 @@ D3D11DXVA2Manager::ConfigureForSize(uint
   gfx::IntSize size(mWidth, mHeight);
   hr = E_FAIL;
   mozilla::mscom::EnsureMTA([&]() -> void {
     hr =
       mTransform->SetMediaTypes(inputType, outputType, ConfigureOutput, &size);
   });
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-  mConfiuredForSize = true;
+  mConfiguredForSize = true;
 
   return S_OK;
 }
 
 bool
 D3D11DXVA2Manager::CanCreateDecoder(const D3D11_VIDEO_DECODER_DESC& aDesc,
                                     const float aFramerate) const
 {
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -26,16 +26,18 @@
 #include "nsComponentManagerUtils.h"
 #include "nsIGfxInfo.h"
 #include "nsIWindowsRegKey.h"
 #include "nsServiceManagerUtils.h"
 #include "nsWindowsHelpers.h"
 #include "prsystem.h"
 #include "nsIXULRuntime.h"
 #include "mozilla/mscom/EnsureMTA.h"
+#include <algorithm>
+#include <vector>
 
 extern const GUID CLSID_WebmMfVpxDec;
 extern const GUID CLSID_AMDWebmMfVp9Dec;
 
 namespace mozilla {
 
 static Atomic<bool> sDXVAEnabled(false);
 
@@ -199,16 +201,27 @@ WMFDecoderModule::Supports(const TrackIn
   const auto videoInfo = aTrackInfo.GetAsVideoInfo();
   if (videoInfo && !SupportsBitDepth(videoInfo->mBitDepth, aDiagnostics)) {
     return false;
   }
 
   if ((aTrackInfo.mMimeType.EqualsLiteral("audio/mp4a-latm") ||
        aTrackInfo.mMimeType.EqualsLiteral("audio/mp4")) &&
        WMFDecoderModule::HasAAC()) {
+    const auto audioInfo = aTrackInfo.GetAsAudioInfo();
+    if (audioInfo && audioInfo->mRate > 0) {
+      // Supported sampling rates per:
+      // https://msdn.microsoft.com/en-us/library/windows/desktop/dd742784(v=vs.85).aspx
+      const std::vector<uint32_t> frequencies = {
+        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
+      };
+      return std::find(frequencies.begin(),
+                       frequencies.end(),
+                       audioInfo->mRate) != frequencies.end();
+    }
     return true;
   }
   if (MP4Decoder::IsH264(aTrackInfo.mMimeType) && WMFDecoderModule::HasH264()) {
     return true;
   }
   if (aTrackInfo.mMimeType.EqualsLiteral("audio/mpeg") &&
       CanCreateWMFDecoder<CLSID_CMP3DecMediaObject>()) {
     return true;
--- a/dom/media/platforms/wrappers/H264Converter.cpp
+++ b/dom/media/platforms/wrappers/H264Converter.cpp
@@ -224,17 +224,24 @@ H264Converter::ShutdownDecoder()
 }
 
 bool
 H264Converter::IsHardwareAccelerated(nsACString& aFailureReason) const
 {
   if (mDecoder) {
     return mDecoder->IsHardwareAccelerated(aFailureReason);
   }
+#ifdef MOZ_APPLEMEDIA
+  // On mac, we can assume H264 is hardware accelerated for now.
+  // This allows MediaCapabilities to report that playback will be smooth.
+  // Which will always be.
+  return true;
+#else
   return MediaDataDecoder::IsHardwareAccelerated(aFailureReason);
+#endif
 }
 
 void
 H264Converter::SetSeekThreshold(const media::TimeUnit& aTime)
 {
   if (mDecoder) {
     mDecoder->SetSeekThreshold(aTime);
   } else {
--- a/dom/media/systemservices/MediaUtils.h
+++ b/dom/media/systemservices/MediaUtils.h
@@ -2,22 +2,22 @@
 /* vim: set sw=2 ts=8 et ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_MediaUtils_h
 #define mozilla_MediaUtils_h
 
-#include "AutoTaskQueue.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/SharedThreadPool.h"
+#include "mozilla/TaskQueue.h"
 #include "mozilla/UniquePtr.h"
 #include "nsCOMPtr.h"
 #include "nsIAsyncShutdown.h"
 #include "nsISupportsImpl.h"
 #include "nsThreadUtils.h"
 
 class nsIEventTarget;
 
@@ -433,20 +433,19 @@ template<typename ResolveValueType,
          typename RejectFunction>
 void
 Await(
   already_AddRefed<nsIEventTarget> aPool,
   RefPtr<MozPromise<ResolveValueType, RejectValueType, true>> aPromise,
   ResolveFunction&& aResolveFunction,
   RejectFunction&& aRejectFunction)
 {
-  RefPtr<AutoTaskQueue> taskQueue =
-    new AutoTaskQueue(std::move(aPool), "MozPromiseAwait");
-  // We can't use a Monitor allocated on the stack (see bug 1426067)
-  Monitor& mon = taskQueue->Monitor();
+  RefPtr<TaskQueue> taskQueue =
+    new TaskQueue(std::move(aPool), "MozPromiseAwait");
+  Monitor mon(__func__);
   bool done = false;
 
   aPromise->Then(taskQueue,
                  __func__,
                  [&](ResolveValueType&& aResolveValue) {
                    MonitorAutoLock lock(mon);
                    aResolveFunction(std::forward<ResolveValueType>(aResolveValue));
                    done = true;
@@ -466,20 +465,19 @@ Await(
 }
 
 template<typename ResolveValueType, typename RejectValueType, bool Excl>
 typename MozPromise<ResolveValueType, RejectValueType, Excl>::
   ResolveOrRejectValue
 Await(already_AddRefed<nsIEventTarget> aPool,
       RefPtr<MozPromise<ResolveValueType, RejectValueType, Excl>> aPromise)
 {
-  RefPtr<AutoTaskQueue> taskQueue =
-    new AutoTaskQueue(std::move(aPool), "MozPromiseAwait");
-  // We can't use a Monitor allocated on the stack (see bug 1426067)
-  Monitor& mon = taskQueue->Monitor();
+  RefPtr<TaskQueue> taskQueue =
+    new TaskQueue(std::move(aPool), "MozPromiseAwait");
+  Monitor mon(__func__);
   bool done = false;
 
   typename MozPromise<ResolveValueType, RejectValueType, Excl>::ResolveOrRejectValue val;
   aPromise->Then(taskQueue,
                  __func__,
                  [&](ResolveValueType aResolveValue) {
                    val.SetResolve(std::move(aResolveValue));
                    MonitorAutoLock lock(mon);
@@ -513,36 +511,38 @@ void
 AwaitAll(already_AddRefed<nsIEventTarget> aPool,
          nsTArray<RefPtr<MozPromise<ResolveValueType, RejectValueType, true>>>&
            aPromises,
          ResolveFunction&& aResolveFunction,
          RejectFunction&& aRejectFunction)
 {
   typedef MozPromise<ResolveValueType, RejectValueType, true> Promise;
   RefPtr<nsIEventTarget> pool = aPool;
-  RefPtr<AutoTaskQueue> taskQueue =
-    new AutoTaskQueue(do_AddRef(pool), "MozPromiseAwaitAll");
-  RefPtr<typename Promise::AllPromiseType> p = Promise::All(taskQueue, aPromises);
-  Await(pool.forget(), p, std::move(aResolveFunction), std::move(aRejectFunction));
+  RefPtr<TaskQueue> taskQueue =
+    new TaskQueue(do_AddRef(pool), "MozPromiseAwaitAll");
+  RefPtr<typename Promise::AllPromiseType> p =
+    Promise::All(taskQueue, aPromises);
+  Await(
+    pool.forget(), p, std::move(aResolveFunction), std::move(aRejectFunction));
 }
 
 // Note: only works with exclusive MozPromise, as Promise::All would attempt
 // to perform copy of nsTArrays which are disallowed.
 template<typename ResolveValueType, typename RejectValueType>
 typename MozPromise<ResolveValueType,
                     RejectValueType,
                     true>::AllPromiseType::ResolveOrRejectValue
 AwaitAll(already_AddRefed<nsIEventTarget> aPool,
          nsTArray<RefPtr<MozPromise<ResolveValueType, RejectValueType, true>>>&
            aPromises)
 {
   typedef MozPromise<ResolveValueType, RejectValueType, true> Promise;
   RefPtr<nsIEventTarget> pool = aPool;
-  RefPtr<AutoTaskQueue> taskQueue =
-    new AutoTaskQueue(do_AddRef(pool), "MozPromiseAwaitAll");
+  RefPtr<TaskQueue> taskQueue =
+    new TaskQueue(do_AddRef(pool), "MozPromiseAwaitAll");
   RefPtr<typename Promise::AllPromiseType> p =
     Promise::All(taskQueue, aPromises);
   return Await(pool.forget(), p);
 }
 
 } // namespace media
 } // namespace mozilla
 
--- a/dom/media/wave/WaveDecoder.cpp
+++ b/dom/media/wave/WaveDecoder.cpp
@@ -24,9 +24,34 @@ WaveDecoder::IsSupportedType(const Media
             aContainerType.ExtendedType().Codecs() == "1" ||
             aContainerType.ExtendedType().Codecs() == "6" ||
             aContainerType.ExtendedType().Codecs() == "7");
   }
 
   return false;
 }
 
+/* static */ nsTArray<UniquePtr<TrackInfo>>
+WaveDecoder::GetTracksInfo(const MediaContainerType& aType)
+{
+  nsTArray<UniquePtr<TrackInfo>> tracks;
+  if (!IsSupportedType(aType)) {
+    return tracks;
+  }
+
+  const MediaCodecs& codecs = aType.ExtendedType().Codecs();
+  if (codecs.IsEmpty()) {
+    tracks.AppendElement(
+      CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+        NS_LITERAL_CSTRING("audio/x-wav"), aType));
+    return tracks;
+  }
+
+  for (const auto& codec : codecs.Range()) {
+    tracks.AppendElement(
+      CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
+        NS_LITERAL_CSTRING("audio/wave; codecs=") + NS_ConvertUTF16toUTF8(codec),
+        aType));
+  }
+  return tracks;
+}
+
 } // namespace mozilla
--- a/dom/media/wave/WaveDecoder.h
+++ b/dom/media/wave/WaveDecoder.h
@@ -1,23 +1,29 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(WaveDecoder_h_)
 #define WaveDecoder_h_
 
+#include "mozilla/UniquePtr.h"
+#include "nsTArray.h"
+
 namespace mozilla {
 
 class MediaContainerType;
+class TrackInfo;
 
 class WaveDecoder
 {
 public:
   // Returns true if the Wave backend is pref'ed on, and we're running on a
   // platform that is likely to have decoders for the format.