Merge mozilla-central to autoland
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 14 Oct 2016 12:34:25 +0200
changeset 317946 0d101ebfd95cf7f63fd036e5d951b84f27ac6a4d
parent 317834 ec4c356610afd0c81ae3196552ce8f4955eaea42 (current diff)
parent 317945 1391a2889aeb2bdd61ad6ef838e65826e35aabc2 (diff)
child 317947 b66b75c2d042101b954e6423438cc07955c2b9bd
push id33170
push usercbook@mozilla.com
push dateFri, 14 Oct 2016 10:37:07 +0000
treeherderautoland@0d101ebfd95c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland
b2g/chrome/content/runapp.js
b2g/components/WebappsUpdateTimer.js
b2g/components/WebappsUpdater.jsm
b2g/components/test/mochitest/app/client.html
b2g/components/test/mochitest/app/index.html
b2g/components/test/mochitest/app/manifest.webapp
b2g/components/test/mochitest/app/manifest.webapp^headers^
b2g/components/test/mochitest/app/sw.sjs
b2g/components/test/mochitest/app/version.html
b2g/components/test/mochitest/app/wait_for_update.html
b2g/components/test/mochitest/chrome.ini
b2g/components/test/mochitest/test_aboutserviceworkers.html
browser/themes/linux/downloads/buttons.png
browser/themes/osx/downloads/buttons.png
browser/themes/osx/downloads/buttons@2x.png
browser/themes/windows/downloads/buttons-XP.png
browser/themes/windows/downloads/buttons.png
caps/tests/mochitest/test_principal_jarprefix_origin_appid_appstatus.html
devtools/server/actors/webapps.js
devtools/shared/apps/tests/data/app-certified.zip
devtools/shared/apps/tests/data/app-overload.zip
devtools/shared/apps/tests/data/app-redirect.zip
devtools/shared/apps/tests/data/app-system.zip
devtools/shared/apps/tests/data/app-updated.zip
devtools/shared/apps/tests/data/app.zip
devtools/shared/apps/tests/debugger-protocol-helper.js
devtools/shared/apps/tests/mochitest.ini
devtools/shared/apps/tests/redirect.sjs
devtools/shared/apps/tests/test_webapps_actor.html
dom/apps/AppDownloadManager.jsm
dom/apps/FreeSpaceWatcher.jsm
dom/apps/ImportExport.jsm
dom/apps/Langpacks.jsm
dom/apps/OfflineCacheInstaller.jsm
dom/apps/OperatorApps.jsm
dom/apps/ScriptPreloader.jsm
dom/apps/StoreTrustAnchor.jsm
dom/apps/Webapps.js
dom/apps/Webapps.jsm
dom/apps/Webapps.manifest
dom/apps/tests/apps/bad_content_type.webapp
dom/apps/tests/apps/basic.webapp
dom/apps/tests/apps/basic.webapp^headers^
dom/apps/tests/apps/installs_allowed_from_chrome_mochitests.webapp
dom/apps/tests/apps/installs_allowed_from_chrome_mochitests.webapp^headers^
dom/apps/tests/apps/installs_allowed_from_example.com.webapp
dom/apps/tests/apps/installs_allowed_from_example.com.webapp^headers^
dom/apps/tests/apps/invalid_activity_href.webapp
dom/apps/tests/apps/invalid_activity_href.webapp^headers^
dom/apps/tests/apps/invalid_activity_href2.webapp
dom/apps/tests/apps/invalid_activity_href2.webapp^headers^
dom/apps/tests/apps/invalid_entry_point.webapp
dom/apps/tests/apps/invalid_entry_point.webapp^headers^
dom/apps/tests/apps/invalid_launch_path.webapp
dom/apps/tests/apps/invalid_launch_path.webapp^headers^
dom/apps/tests/apps/invalid_launch_path2.webapp
dom/apps/tests/apps/invalid_launch_path2.webapp^headers^
dom/apps/tests/apps/invalid_locale_entry_point.webapp
dom/apps/tests/apps/invalid_locale_entry_point.webapp^headers^
dom/apps/tests/apps/invalid_message.webapp
dom/apps/tests/apps/invalid_message.webapp^headers^
dom/apps/tests/apps/json_syntax_error.webapp
dom/apps/tests/apps/json_syntax_error.webapp^headers^
dom/apps/tests/apps/launch_paths.webapp
dom/apps/tests/apps/launch_paths.webapp^headers^
dom/apps/tests/apps/missing_required_field.webapp
dom/apps/tests/apps/missing_required_field.webapp^headers^
dom/apps/tests/apps/no_delegated_install.webapp
dom/apps/tests/apps/no_delegated_install.webapp^headers^
dom/apps/tests/apps/utf8.webapp
dom/apps/tests/apps/utf8.webapp^headers^
dom/apps/tests/asmjs/asmjs_app.sjs
dom/apps/tests/asmjs/index.html
dom/apps/tests/asmjs/manifest.webapp
dom/apps/tests/chromeAddCert.js
dom/apps/tests/common.js
dom/apps/tests/cross_origin.html
dom/apps/tests/file_app.sjs
dom/apps/tests/file_app.template.html
dom/apps/tests/file_bug_779982.html
dom/apps/tests/file_bug_779982.js
dom/apps/tests/file_bug_945152.html
dom/apps/tests/file_bug_945152.sjs
dom/apps/tests/file_cached_app.template.appcache
dom/apps/tests/file_cached_app.template.webapp
dom/apps/tests/file_hosted_app.template.webapp
dom/apps/tests/file_hosted_certified.webapp
dom/apps/tests/file_hosted_certified.webapp^headers^
dom/apps/tests/file_invalidWidget_app.template.webapp
dom/apps/tests/file_manifest.json
dom/apps/tests/file_manifest.json^headers^
dom/apps/tests/file_packaged_app.sjs
dom/apps/tests/file_packaged_app.template.html
dom/apps/tests/file_packaged_app.template.webapp
dom/apps/tests/file_script.template.js
dom/apps/tests/file_test_widget.js
dom/apps/tests/file_widget_app.template.html
dom/apps/tests/file_widget_app.template.webapp
dom/apps/tests/icon15.png
dom/apps/tests/icon15alternate.png
dom/apps/tests/icon48.png
dom/apps/tests/install_and_redirect_helper.xul
dom/apps/tests/langpack/event.html
dom/apps/tests/langpack/fr/app.json
dom/apps/tests/langpack/fr/app.properties
dom/apps/tests/langpack/fr/manifest.json
dom/apps/tests/langpack/index.html
dom/apps/tests/langpack/lang1.webapp
dom/apps/tests/langpack/lang1.webapp^headers^
dom/apps/tests/langpack/lang2.webapp
dom/apps/tests/langpack/lang2.webapp^headers^
dom/apps/tests/langpack/localizedvalues.html
dom/apps/tests/langpack/manifest.webapp
dom/apps/tests/langpack/manifest.webapp^headers^
dom/apps/tests/langpack/manifest_no_version.webapp
dom/apps/tests/langpack/manifest_version_xyz.webapp
dom/apps/tests/langpack/resources.html
dom/apps/tests/marketplace/marketplace_app.webapp
dom/apps/tests/marketplace/marketplace_app.webapp^headers^
dom/apps/tests/marketplace/marketplace_app.zip
dom/apps/tests/marketplace/marketplace_dev_app.webapp
dom/apps/tests/marketplace/marketplace_dev_app.webapp^headers^
dom/apps/tests/marketplace/marketplace_dev_app.zip
dom/apps/tests/marketplace/marketplace_dev_privileged_app.webapp
dom/apps/tests/marketplace/marketplace_dev_privileged_app.webapp^headers^
dom/apps/tests/marketplace/marketplace_dev_privileged_app.zip
dom/apps/tests/marketplace/marketplace_dev_reviewers_app.webapp
dom/apps/tests/marketplace/marketplace_dev_reviewers_app.webapp^headers^
dom/apps/tests/marketplace/marketplace_dev_reviewers_app.zip
dom/apps/tests/marketplace/marketplace_privileged_app.webapp
dom/apps/tests/marketplace/marketplace_privileged_app.webapp^headers^
dom/apps/tests/marketplace/marketplace_privileged_app.zip
dom/apps/tests/marketplace/marketplace_reviewers_app.webapp
dom/apps/tests/marketplace/marketplace_reviewers_app.webapp^headers^
dom/apps/tests/marketplace/marketplace_reviewers_app.zip
dom/apps/tests/marketplace/marketplace_stage_app.webapp
dom/apps/tests/marketplace/marketplace_stage_app.webapp^headers^
dom/apps/tests/marketplace/marketplace_stage_app.zip
dom/apps/tests/marketplace/marketplace_stage_privileged_app.webapp
dom/apps/tests/marketplace/marketplace_stage_privileged_app.webapp^headers^
dom/apps/tests/marketplace/marketplace_stage_privileged_app.zip
dom/apps/tests/marketplace/marketplace_stage_reviewers_app.webapp
dom/apps/tests/marketplace/marketplace_stage_reviewers_app.webapp^headers^
dom/apps/tests/marketplace/marketplace_stage_reviewers_app.zip
dom/apps/tests/mochitest.ini
dom/apps/tests/pkg_install_iframe.html
dom/apps/tests/signed/corrupt_app_1.zip
dom/apps/tests/signed/origin_app_1.zip
dom/apps/tests/signed/unknown_issuer_app_1.zip
dom/apps/tests/signed/unsigned_app_1.zip
dom/apps/tests/signed/unsigned_app_2.zip
dom/apps/tests/signed/valid_app_1.zip
dom/apps/tests/signed/valid_app_2.zip
dom/apps/tests/signed_app.sjs
dom/apps/tests/signed_app_template.webapp
dom/apps/tests/test_app_enabled.html
dom/apps/tests/test_app_update.html
dom/apps/tests/test_bug_1168300.html
dom/apps/tests/test_bug_765063.xul
dom/apps/tests/test_bug_771294.xul
dom/apps/tests/test_bug_779982.html
dom/apps/tests/test_bug_795164.html
dom/apps/tests/test_bug_945152.html
dom/apps/tests/test_checkInstalled.html
dom/apps/tests/test_cross_origin.xul
dom/apps/tests/test_import_export.html
dom/apps/tests/test_install_app.xul
dom/apps/tests/test_install_dev_mode.html
dom/apps/tests/test_install_errors.xul
dom/apps/tests/test_install_multiple_apps_origin.html
dom/apps/tests/test_install_receipts.html
dom/apps/tests/test_install_utf8.xul
dom/apps/tests/test_langpacks.html
dom/apps/tests/test_launch_paths.xul
dom/apps/tests/test_list_api.xul
dom/apps/tests/test_marketplace_pkg_install.html
dom/apps/tests/test_operator_app_install.js
dom/apps/tests/test_operator_app_install.xul
dom/apps/tests/test_packaged_app_asmjs.html
dom/apps/tests/test_packaged_app_common.js
dom/apps/tests/test_packaged_app_install.html
dom/apps/tests/test_packaged_app_update.html
dom/apps/tests/test_receipt_operations.html
dom/apps/tests/test_signed_pkg_install.html
dom/apps/tests/test_theme_role.html
dom/apps/tests/test_third_party_homescreen.html
dom/apps/tests/test_uninstall_errors.html
dom/apps/tests/test_web_app_install.html
dom/apps/tests/test_widget.html
dom/apps/tests/test_widget_browser.html
dom/apps/tests/unit/head.js
dom/apps/tests/unit/tail.js
dom/broadcastchannel/tests/manifest.webapp
dom/broadcastchannel/tests/server.sjs
dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser.html
dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser2.html
dom/browser-element/mochitest/browserElement_AllowEmbedAppsInNestedOOIframe.js
dom/browser-element/mochitest/browserElement_AppFramePermission.js
dom/browser-element/mochitest/browserElement_AppWindowNamespace.js
dom/browser-element/mochitest/browserElement_CloseApp.js
dom/browser-element/mochitest/browserElement_DisallowEmbedAppsInOOP.js
dom/browser-element/mochitest/browserElement_MultipleAudioChannels.js
dom/browser-element/mochitest/file_browserElement_AllowEmbedAppsInNestedOOIframe.html
dom/browser-element/mochitest/file_browserElement_AppFramePermission.html
dom/browser-element/mochitest/file_browserElement_AppWindowNamespace.html
dom/browser-element/mochitest/file_browserElement_CloseApp.html
dom/browser-element/mochitest/file_browserElement_DisallowEmbedAppsInOOP.html
dom/browser-element/mochitest/file_browserElement_MultipleAudioChannels.html
dom/browser-element/mochitest/multipleAudioChannels_manifest.webapp
dom/browser-element/mochitest/multipleAudioChannels_manifest.webapp^headers^
dom/browser-element/mochitest/priority/test_BackgroundLRU.html
dom/browser-element/mochitest/priority/test_MultipleActivities.html
dom/browser-element/mochitest/test_browserElement_MultipleAudioChannels.html
dom/browser-element/mochitest/test_browserElement_inproc_AppFramePermission.html
dom/browser-element/mochitest/test_browserElement_inproc_AppWindowNamespace.html
dom/browser-element/mochitest/test_browserElement_inproc_CloseApp.html
dom/browser-element/mochitest/test_browserElement_inproc_DisallowEmbedAppsInOOP.html
dom/browser-element/mochitest/test_browserElement_oop_AllowEmbedAppsInNestedOOIframe.html
dom/browser-element/mochitest/test_browserElement_oop_AppFramePermission.html
dom/browser-element/mochitest/test_browserElement_oop_AppWindowNamespace.html
dom/browser-element/mochitest/test_browserElement_oop_CloseApp.html
dom/browser-element/mochitest/test_browserElement_oop_DisallowEmbedAppsInOOP.html
dom/cache/test/mochitest/app/after_clear.html
dom/cache/test/mochitest/app/before_clear.html
dom/cache/test/mochitest/app/index.html
dom/cache/test/mochitest/app/manifest.webapp
dom/cache/test/mochitest/app/manifest.webapp^headers^
dom/cache/test/mochitest/app/sw.js
dom/cache/test/mochitest/app/test.js
dom/cache/test/mochitest/test_cache_clear_on_app_uninstall.html
dom/downloads/tests/common_app.js
dom/downloads/tests/file_app.sjs
dom/downloads/tests/file_app.template.webapp
dom/downloads/tests/shim_app_as_test.js
dom/downloads/tests/shim_app_as_test_chrome.js
dom/downloads/tests/test_downloads_adopt_download.html
dom/downloads/tests/testapp_downloads_adopt_download.html
dom/downloads/tests/testapp_downloads_adopt_download.js
dom/downloads/tests/testapp_downloads_adopt_download.manifest
dom/indexedDB/test/test_webapp_clearBrowserData_inproc_inproc.html
dom/indexedDB/test/test_webapp_clearBrowserData_inproc_oop.html
dom/indexedDB/test/test_webapp_clearBrowserData_oop_inproc.html
dom/indexedDB/test/webapp_clearBrowserData.js
dom/indexedDB/test/webapp_clearBrowserData_appFrame.html
dom/indexedDB/test/webapp_clearBrowserData_browserFrame.html
dom/ipc/tests/file_app.sjs
dom/ipc/tests/file_app.template.webapp
dom/ipc/tests/test_permission_embed.html
dom/ipc/tests/test_permission_for_in_process_app.html
dom/ipc/tests/test_permission_for_nested_oop_app.html
dom/ipc/tests/test_permission_for_oop_app.html
dom/ipc/tests/test_permission_for_two_oop_apps.html
dom/ipc/tests/test_permission_framescript.js
dom/ipc/tests/test_permission_helper.js
dom/ipc/tests/test_permission_when_oop_app_crashes.html
dom/messagechannel/MessagePortList.cpp
dom/messagechannel/MessagePortList.h
dom/permission/tests/test_permission_basics.html
dom/permission/tests/test_webapps-manage.html
dom/security/test/csp/chrome.ini
dom/security/test/csp/file_bug768029.html
dom/security/test/csp/file_bug773891.html
dom/security/test/csp/file_bug773891.sjs
dom/security/test/csp/test_bug768029.html
dom/security/test/csp/test_bug773891.html
dom/security/test/csp/test_bug949549.html
dom/tests/browser/browser_webapps_permissions.js
dom/tests/browser/browser_webapps_perms_reinstall.js
dom/tests/browser/test-webapp-original.webapp
dom/tests/browser/test-webapp-reinstall.webapp
dom/tests/browser/test-webapp.webapp
dom/tests/browser/test-webapps-permissions.html
dom/tests/mochitest/fetch/app-protocol/README.txt
dom/tests/mochitest/fetch/app-protocol/application.zip
dom/tests/mochitest/fetch/app-protocol/foo.txt
dom/tests/mochitest/fetch/app-protocol/index.html
dom/tests/mochitest/fetch/app-protocol/manifest.webapp
dom/tests/mochitest/fetch/app-protocol/update.webapp
dom/tests/mochitest/fetch/app-protocol/update.webapp^headers^
dom/tests/mochitest/fetch/test_fetch_app_protocol.html
dom/tests/mochitest/localstorage/frameAppIsolation.html
dom/tests/mochitest/localstorage/frame_clear_browser_data.html
dom/tests/mochitest/localstorage/test_appIsolation.html
dom/tests/mochitest/localstorage/test_app_uninstall.html
dom/tests/mochitest/localstorage/test_clear_browser_data.html
dom/tests/mochitest/notification/test_notification_resend.html
dom/webidl/Apps.webidl
dom/webidl/MessagePortList.webidl
extensions/cookie/test/channel_utils.js
extensions/cookie/test/chrome.ini
extensions/cookie/test/test_app_uninstall_cookies.html
extensions/cookie/test/test_app_uninstall_permissions.html
extensions/cookie/test/test_permissionmanager_app_isolation.html
js/src/asmjs/WasmCode.cpp
js/src/asmjs/WasmCode.h
netwerk/test/mochitests/test_web_packaged_app.html
testing/mochitest/tests/Harness_sanity/app.html
testing/mochitest/tests/Harness_sanity/file_app.sjs
testing/mochitest/tests/Harness_sanity/file_app.template.webapp
testing/mochitest/tests/Harness_sanity/test_SpecialPowersPushAppPermissions.html
testing/mochitest/tests/Harness_sanity/test_bug816847.html
new file mode 100644
--- /dev/null
+++ b/.cargo/.gitignore
@@ -0,0 +1,1 @@
+config
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1300895 - Needed clobber to fix mochitests on windows 7 vm opt?
+Bug 1261019 - Clobber on OS X to fix bustage caused by removed files
--- a/addon-sdk/source/python-lib/cuddlefish/prefs.py
+++ b/addon-sdk/source/python-lib/cuddlefish/prefs.py
@@ -224,17 +224,16 @@ DEFAULT_TEST_PREFS = {
     # Indicate that the download panel has been shown once so that whichever
     # download test runs first doesn't show the popup inconsistently.
     'browser.download.panel.shown': True,
     # Assume the about:newtab page's intro panels have been shown to not depend on
     # which test runs first and happens to open about:newtab
     'browser.newtabpage.introShown': True,
     # Disable useragent updates.
     'general.useragent.updates.enabled': False,
-    'dom.mozApps.debug': True,
     'dom.apps.customization.enabled': True,
     'media.eme.enabled': True,
     'media.eme.apiVisible': True,
     # Don't forceably kill content processes after a timeout
     'dom.ipc.tabs.shutdownTimeoutSecs': 0,
     'general.useragent.locale': "en-US",
     'intl.locale.matchOS': "en-US",
     'dom.indexedDB.experimental': True
--- a/addon-sdk/source/test/preferences/test.json
+++ b/addon-sdk/source/test/preferences/test.json
@@ -32,17 +32,16 @@
   "layout.css.grid.enabled": true,
   "layout.spammy_warnings.enabled": false,
   "dom.mozSettings.enabled": true,
   "network.http.bypass-cachelock-threshold": 200000,
   "geo.provider.testing": true,
   "browser.pagethumbnails.capturing_disabled": true,
   "browser.download.panel.shown": true,
   "general.useragent.updates.enabled": false,
-  "dom.mozApps.debug": true,
   "dom.apps.customization.enabled": true,
   "media.eme.enabled": true,
   "media.eme.apiVisible": true,
   "dom.ipc.tabs.shutdownTimeoutSecs": 0,
   "general.useragent.locale": "en-US",
   "intl.locale.matchOS": "en-US",
   "dom.indexedDB.experimental": true
 }
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -871,21 +871,16 @@ pref("gfx.canvas.max-size-for-skia-gl", 
 pref("gfx.gralloc.fence-with-readpixels", true);
 
 // enable screen mirroring to external display
 pref("gfx.screen-mirroring.enabled", true);
 
 // The url of the page used to display network error details.
 pref("b2g.neterror.url", "net_error.html");
 
-// The origin used for the shared themes uri space.
-pref("b2g.theme.origin", "app://theme.gaiamobile.org");
-pref("dom.mozApps.themable", true);
-pref("dom.mozApps.selected_theme", "default_theme.gaiamobile.org");
-
 // Enable PAC generator for B2G.
 pref("network.proxy.pac_generator", true);
 
 // List of app origins to apply browsing traffic proxy setting, separated by
 // comma.  Specify '*' in the list to apply to all apps.
 pref("network.proxy.browsing.app_origins", "app://system.gaiamobile.org");
 
 // Enable Web Speech synthesis API
deleted file mode 100644
--- a/b2g/chrome/content/runapp.js
+++ /dev/null
@@ -1,171 +0,0 @@
-"use strict";
-
-// runapp.js:
-// Provide a --runapp APPNAME command-line option.
-
-var runAppObj;
-window.addEventListener('load', function() {
-  // Get the command line arguments that were passed to the b2g client
-  let args;
-  try {
-    let service = Cc["@mozilla.org/commandlinehandler/general-startup;1?type=b2gcmds"].getService(Ci.nsISupports);
-    args = service.wrappedJSObject.cmdLine;
-  } catch(e) {}
-
-  if (!args) {
-    return;
-  }
-
-  let appname;
-
-  // - Check if the argument is present before doing any work.
-  try {
-    // Returns null if the argument was not specified.  Throws
-    // NS_ERROR_INVALID_ARG if there is no parameter specified (because
-    // it was the last argument or the next argument starts with '-').
-    // However, someone could still explicitly pass an empty argument!
-    appname = args.handleFlagWithParam('runapp', false);
-  } catch(e) {
-    // treat a missing parameter like an empty parameter (=> show usage)
-    appname = '';
-  }
-
-  // not specified, bail.
-  if (appname === null) {
-    return;
-  }
-
-  runAppObj = new AppRunner(appname);
-  Services.obs.addObserver(runAppObj, 'remote-browser-shown', false);
-  Services.obs.addObserver(runAppObj, 'inprocess-browser-shown', false);
-});
-
-window.addEventListener('unload', function() {
-  if (runAppObj) {
-    Services.obs.removeObserver(runAppObj, 'remote-browser-shown');
-    Services.obs.removeObserver(runAppObj, 'inprocess-browser-shown');
-  }
-});
-
-function AppRunner(aName) {
-  this._appName = aName;
-  this._apps = [];
-}
-AppRunner.prototype = {
-  observe: function(aSubject, aTopic, aData) {
-    let frameLoader = aSubject;
-    // get a ref to the app <iframe>
-    frameLoader.QueryInterface(Ci.nsIFrameLoader);
-    // Ignore notifications that aren't from a BrowserOrApp
-    if (!frameLoader.ownerIsMozBrowserOrAppFrame) {
-      return;
-    }
-
-    let frame = frameLoader.ownerElement;
-    if (!frame.appManifestURL) { // Ignore all frames but app frames
-      return;
-    }
-
-    if (aTopic == 'remote-browser-shown' ||
-        aTopic == 'inprocess-browser-shown') {
-      this.doRunApp(frame);
-    }
-  },
-
-  doRunApp: function(currentFrame) {
-    // - Get the list of apps since the parameter was specified
-    if (this._apps.length) {
-      this.getAllSuccess(this._apps, currentFrame)
-    } else {
-      var req = navigator.mozApps.mgmt.getAll();
-      req.onsuccess = function() {
-        this._apps = req.result;
-        this.getAllSuccess(this._apps, currentFrame)
-      }.bind(this);
-      req.onerror = this.getAllError.bind(this);
-    }
-  },
-
-  getAllSuccess: function(apps, currentFrame) {
-    function findAppWithName(name) {
-      let normalizedSearchName = name.replace(/[- ]+/g, '').toLowerCase();
-
-      for (let i = 0; i < apps.length; i++) {
-        let app = apps[i];
-        let normalizedAppName =
-          app.manifest.name.replace(/[- ]+/g, '').toLowerCase();
-        if (normalizedSearchName === normalizedAppName) {
-          return app;
-        }
-      }
-      return null;
-    }
-
-    function usageAndDie(justApps) {
-      if (!justApps)
-        dump(
-          'The --runapp argument specifies an app to automatically run at\n'+
-          'startup.  We match against app names per their manifest and \n' +
-          'ignoring capitalization, dashes, and whitespace.\n' +
-          '\nThe system will load as usual except the lock screen will be ' +
-          'automatically be disabled.\n\n' +
-          'Known apps:\n');
-
-      for (let i = 0; i < apps.length; i++) {
-        dump('  ' + apps[i].manifest.name + '\n');
-      }
-
-      // Exit the b2g client
-      Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
-    }
-
-    if (this._appName === '') {
-      usageAndDie();
-      return;
-    }
-
-    let appsService = Cc["@mozilla.org/AppsService;1"].getService(Ci.nsIAppsService);
-    let currentApp = appsService.getAppByManifestURL(currentFrame.appManifestURL);
-
-    if (!currentApp || currentApp.role !== 'homescreen') {
-      return;
-    }
-
-    let app = findAppWithName(this._appName);
-    if (!app) {
-      dump('Could not find app: "' + this._appName + '". Maybe you meant one of:\n');
-      usageAndDie(true);
-      return;
-    }
-
-    currentFrame.addEventListener('mozbrowserloadend', launchApp);
-
-    function launchApp() {
-      currentFrame.removeEventListener('mozbrowserloadend', launchApp);
-
-      let setReq =
-        navigator.mozSettings.createLock().set({'lockscreen.enabled': false});
-      setReq.onsuccess = function() {
-        // give the event loop 100ms to disable the lock screen
-        window.setTimeout(function() {
-          dump('--runapp launching app: ' + app.manifest.name + '\n');
-          app.launch();
-        }, 100);
-      };
-      setReq.onerror = function() {
-        dump('--runapp failed to disable lock-screen.  Giving up.\n');
-      };
-
-      dump('--runapp found app: ' + app.manifest.name +
-           ', disabling lock screen...\n');
-
-      // Disable observers once we have made the request to launch the app.
-      Services.obs.removeObserver(runAppObj, 'remote-browser-shown');
-      Services.obs.removeObserver(runAppObj, 'inprocess-browser-shown');
-    }
-  },
-
-  getAllError: function() {
-    dump('Problem getting the list of all apps!');
-  }
-};
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -476,56 +476,16 @@ setUpdateTrackingId();
         window.navigator.mozSettings.createLock().set(setting);
       } catch (e) {
         console.log('Unable to read pref layers.low-precision-opacity: ' + e);
       }
     }
   });
 })();
 
-// ================ Theme selection ============
-// theme.selected holds the manifest url of the currently used theme.
-SettingsListener.observe("theme.selected",
-                         "app://default_theme.gaiamobile.org/manifest.webapp",
-                         function(value) {
-  if (!value) {
-    return;
-  }
-
-  let newTheme;
-  try {
-    let enabled = Services.prefs.getBoolPref("dom.mozApps.themable");
-    if (!enabled) {
-      return;
-    }
-
-    // Make sure this is a url, and only keep the host part to set the pref.
-    let uri = Services.io.newURI(value, null, null);
-    // We only support overriding in the app:// protocol handler.
-    if (uri.scheme !== "app") {
-      return;
-    }
-    newTheme = uri.host;
-  } catch(e) {
-    return;
-  }
-
-  let currentTheme;
-  try {
-    currentTheme = Services.prefs.getCharPref('dom.mozApps.selected_theme');
-  } catch(e) {};
-
-  if (currentTheme != newTheme) {
-    debug("New theme selected " + value);
-    Services.prefs.setCharPref('dom.mozApps.selected_theme', newTheme);
-    Services.prefs.savePrefFile(null);
-    Services.obs.notifyObservers(null, 'app-theme-changed', newTheme);
-  }
-});
-
 // =================== Proxy server ======================
 (function setupBrowsingProxySettings() {
   function setPAC() {
     let usePAC;
     try {
       usePAC = Services.prefs.getBoolPref('network.proxy.pac_generator');
     } catch (ex) {}
 
@@ -634,18 +594,16 @@ var settingsToObserve = {
   'devtools.eventlooplag.threshold': 100,
   'devtools.remote.wifi.visible': {
     resetToPref: true
   },
   'devtools.telemetry.supported_performance_marks': {
     resetToPref: true
   },
 
-  'dom.mozApps.use_reviewer_certs': false,
-  'dom.mozApps.signed_apps_installable_from': 'https://marketplace.firefox.com',
   'dom.presentation.discovery.enabled': false,
   'dom.presentation.discoverable': false,
   'dom.serviceWorkers.testing.enabled': false,
   'gfx.layerscope.enabled': false,
   'layers.draw-borders': false,
   'layers.draw-tile-borders': false,
   'layers.dump': false,
   'layers.enable-tiles': AppConstants.platform !== "win",
--- a/b2g/chrome/content/shell.html
+++ b/b2g/chrome/content/shell.html
@@ -30,19 +30,16 @@
 #ifndef ANDROID
 #ifndef MOZ_GRAPHENE
   <!-- various task that has to happen only on desktop -->
   <script type="application/javascript;version=1.8"
           src="chrome://b2g/content/desktop.js"> </script>
   <!-- this script handles the screen argument for desktop builds -->
   <script type="application/javascript;version=1.8"
           src="chrome://b2g/content/screen.js"> </script>
-  <!-- this script handles the "runapp" argument for desktop builds -->
-  <script type="application/javascript;version=1.8"
-          src="chrome://b2g/content/runapp.js"> </script>
 #endif
 #else
   <!-- this file is only loaded on Gonk to manage ADB state -->
   <script type="application/javascript;version=1.8"
           src="chrome://b2g/content/devtools/adb.js"> </script>
 #endif
   <!-- manages DevTools server state -->
   <script type="application/javascript;version=1.8"
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -703,18 +703,16 @@ var shell = {
     this.reportCrash(true);
 
     SystemAppProxy.registerFrame(shell.contentBrowser);
 
     this.sendEvent(window, 'ContentStart');
 
     Services.obs.notifyObservers(null, 'content-start', null);
 
-    isGonk && Cu.import('resource://gre/modules/OperatorApps.jsm');
-
     if (AppConstants.MOZ_GRAPHENE &&
         Services.prefs.getBoolPref("b2g.nativeWindowGeometry.fullscreen")) {
       window.fullScreen = true;
     }
 
     shell.handleCmdLine();
   },
 
@@ -943,19 +941,16 @@ window.addEventListener('ContentStart', 
     } else if (e.detail.type == "delete-crash" && e.detail.crashID) {
       debugCrashReport("deleting crash at user request ", e.detail.crashID);
       shell.deleteCrash(e.detail.crashID);
     }
   });
 });
 
 window.addEventListener('ContentStart', function update_onContentStart() {
-  Cu.import('resource://gre/modules/WebappsUpdater.jsm');
-  WebappsUpdater.handleContentStart(shell);
-
   if (!AppConstants.MOZ_UPDATER) {
     return;
   }
 
   let promptCc = Cc["@mozilla.org/updates/update-prompt;1"];
   if (!promptCc) {
     return;
   }
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -24,17 +24,16 @@ chrome.jar:
   content/devtools/hud.js               (content/devtools/hud.js)
 #ifndef MOZ_WIDGET_GONK
   content/desktop.css                   (content/desktop.css)
   content/images/desktop/home-black.png (content/images/desktop/home-black.png)
   content/images/desktop/home-white.png (content/images/desktop/home-white.png)
   content/images/desktop/rotate.png     (content/images/desktop/rotate.png)
   content/desktop.js                    (content/desktop.js)
   content/screen.js                     (content/screen.js)
-  content/runapp.js                     (content/runapp.js)
 #endif
 * content/content.css                   (content/content.css)
   content/touchcontrols.css             (content/touchcontrols.css)
 
   content/identity.js                   (content/identity.js)
 
 #ifndef MOZ_GRAPHENE
 % override chrome://global/skin/media/videocontrols.css chrome://b2g/content/touchcontrols.css
--- a/b2g/components/B2GComponents.manifest
+++ b/b2g/components/B2GComponents.manifest
@@ -59,21 +59,16 @@ contract @mozilla.org/network/protocol/a
 contract @mozilla.org/network/protocol/about;1?what=neterror {920400b1-cf8f-4760-a9c4-441417b15134}
 
 #ifndef MOZ_GRAPHENE
 # FilePicker.js
 component {436ff8f9-0acc-4b11-8ec7-e293efba3141} FilePicker.js
 contract @mozilla.org/filepicker;1 {436ff8f9-0acc-4b11-8ec7-e293efba3141}
 #endif
 
-# WebappsUpdateTimer.js
-component {637b0f77-2429-49a0-915f-abf5d0db8b9a} WebappsUpdateTimer.js
-contract @mozilla.org/b2g/webapps-update-timer;1 {637b0f77-2429-49a0-915f-abf5d0db8b9a}
-category update-timer WebappsUpdateTimer @mozilla.org/b2g/webapps-update-timer;1,getService,background-update-timer,webapps.update.interval,86400
-
 # FxAccountsUIGlue.js
 component {51875c14-91d7-4b8c-b65d-3549e101228c} FxAccountsUIGlue.js
 contract @mozilla.org/fxaccounts/fxaccounts-ui-glue;1 {51875c14-91d7-4b8c-b65d-3549e101228c}
 
 # HelperAppDialog.js
 component {710322af-e6ae-4b0c-b2c9-1474a87b077e} HelperAppDialog.js
 contract @mozilla.org/helperapplauncherdialog;1 {710322af-e6ae-4b0c-b2c9-1474a87b077e}
 
--- a/b2g/components/ContentPermissionPrompt.js
+++ b/b2g/components/ContentPermissionPrompt.js
@@ -19,17 +19,16 @@ const PROMPT_FOR_UNKNOWN = ["audio-captu
                             "video-capture"];
 // Due to privary issue, permission requests like GetUserMedia should prompt
 // every time instead of providing session persistence.
 const PERMISSION_NO_SESSION = ["audio-capture", "video-capture"];
 const ALLOW_MULTIPLE_REQUESTS = ["audio-capture", "video-capture"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Webapps.jsm");
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
 Cu.import("resource://gre/modules/PermissionsTable.jsm");
 
 var permissionManager = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
 var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
 
 var permissionSpecificChecker = {};
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -7,17 +7,16 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/WebappsUpdater.jsm");
 Cu.import("resource://gre/modules/AppConstants.jsm");
 
 const VERBOSE = 1;
 var log =
   VERBOSE ?
   function log_dump(msg) { dump("UpdatePrompt: "+ msg +"\n"); } :
   function log_noop(msg) { };
 
@@ -134,17 +133,16 @@ UpdateCheckListener.prototype = {
     Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
     Services.aus.onError(request, update);
   }
 };
 
 function UpdatePrompt() {
   this.wrappedJSObject = this;
   this._updateCheckListener = new UpdateCheckListener(this);
-  Services.obs.addObserver(this, "update-check-start", false);
 }
 
 UpdatePrompt.prototype = {
   classID: Components.ID("{88b3eb21-d072-4e3b-886d-f89d8c49fe59}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt,
                                          Ci.nsIUpdateCheckListener,
                                          Ci.nsIRequestObserver,
                                          Ci.nsIProgressEventSink,
@@ -636,19 +634,16 @@ UpdatePrompt.prototype = {
       case "idle":
         this._waitingForIdle = false;
         this.showApplyPrompt(this._update);
         // Fall through
       case "quit-application":
         Services.idle.removeIdleObserver(this, this.applyIdleTimeout / 1000);
         Services.obs.removeObserver(this, "quit-application");
         break;
-      case "update-check-start":
-        WebappsUpdater.updateApps();
-        break;
     }
   },
 
   // nsITimerCallback
 
   notify: function UP_notify(aTimer) {
     if (aTimer == this._applyPromptTimer) {
       log("Timed out waiting for result, restarting");
deleted file mode 100644
--- a/b2g/components/WebappsUpdateTimer.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/* 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/. */
-
-/**
- * This component triggers an app update check even when system updates are
- * disabled to make sure we always check for app updates.
- */
-
-"use strict";
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/WebappsUpdater.jsm");
-
-function debug(aStr) {
-  //dump("--*-- WebappsUpdateTimer: " + aStr);
-}
-
-function WebappsUpdateTimer() {
-}
-
-WebappsUpdateTimer.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]),
-  classID: Components.ID("{637b0f77-2429-49a0-915f-abf5d0db8b9a}"),
-
-  notify: function(aTimer) {
-    try {
-      // We want to check app updates if system updates are disabled or
-      // if they update frecency is not daily.
-      if (Services.prefs.getBoolPref("app.update.enabled") === true &&
-          Services.prefs.getIntPref("app.update.interval") === 86400) {
-        return;
-      }
-    } catch(e) {
-      // That should never happen..
-    }
-
-    // If we are offline, wait to be online to start the update check.
-    if (Services.io.offline) {
-      debug("Network is offline. Setting up an offline status observer.");
-      Services.obs.addObserver(this, "network:offline-status-changed", false);
-      return;
-    }
-
-    // This will trigger app updates in b2g/components/WebappsUpdater.jsm
-    // that also takes care of notifying gaia.
-    WebappsUpdater.updateApps();
-  },
-
-  observe: function(aSubject, aTopic, aData) {
-    if (aTopic !== "network:offline-status-changed" ||
-        aData !== "online") {
-      return;
-    }
-
-    debug("Network is online. Checking updates.");
-    Services.obs.removeObserver(this, "network:offline-status-changed");
-    WebappsUpdater.updateApps();
-  }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsUpdateTimer]);
deleted file mode 100644
--- a/b2g/components/WebappsUpdater.jsm
+++ /dev/null
@@ -1,109 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["WebappsUpdater"];
-
-const Cc = Components.classes;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "settings",
-                                   "@mozilla.org/settingsService;1",
-                                   "nsISettingsService");
-
-XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
-                                  "resource://gre/modules/SystemAppProxy.jsm");
-
-function debug(aStr) {
-  //dump("--*-- WebappsUpdater: " + aStr);
-}
-
-this.WebappsUpdater = {
-  _checkingApps: false,
-
-  handleContentStart: function() {
-  },
-
-  sendChromeEvent: function(aType, aDetail) {
-    let detail = aDetail || {};
-    detail.type = aType;
-
-    let sent = SystemAppProxy.dispatchEvent(detail);
-    if (!sent) {
-      debug("Warning: Couldn't send update event " + aType +
-          ": no content browser. Will send again when content becomes available.");
-      return false;
-    }
-
-    return true;
-  },
-
-  _appsUpdated: function(aApps) {
-    debug("appsUpdated: " + aApps.length + " apps to update");
-    let lock = settings.createLock();
-    lock.set("apps.updateStatus", "check-complete", null);
-    this.sendChromeEvent("apps-update-check", { apps: aApps });
-    this._checkingApps = false;
-  },
-
-  // Trigger apps update check and wait for all to be done before
-  // notifying gaia.
-  updateApps: function() {
-    debug("updateApps (" + this._checkingApps + ")");
-    // Don't start twice.
-    if (this._checkingApps) {
-      return;
-    }
-
-    let allowUpdate = true;
-    try {
-      allowUpdate = Services.prefs.getBoolPref("webapps.update.enabled");
-    } catch (ex) { }
-
-    if (!allowUpdate) {
-      return;
-    }
-
-    this._checkingApps = true;
-
-    let self = this;
-
-    let window = Services.wm.getMostRecentWindow("navigator:browser");
-    let all = window.navigator.mozApps.mgmt.getAll();
-
-    all.onsuccess = function() {
-      let appsCount = this.result.length;
-      let appsChecked = 0;
-      let appsToUpdate = [];
-      this.result.forEach(function updateApp(aApp) {
-        let update = aApp.checkForUpdate();
-        update.onsuccess = function() {
-          if (aApp.downloadAvailable) {
-            appsToUpdate.push(aApp.manifestURL);
-          }
-
-          appsChecked += 1;
-          if (appsChecked == appsCount) {
-            self._appsUpdated(appsToUpdate);
-          }
-        }
-        update.onerror = function() {
-          appsChecked += 1;
-          if (appsChecked == appsCount) {
-            self._appsUpdated(appsToUpdate);
-          }
-        }
-      });
-    }
-
-    all.onerror = function() {
-      // Could not get the app list, just notify to update nothing.
-      self._appsUpdated([]);
-    }
-  }
-};
--- a/b2g/components/moz.build
+++ b/b2g/components/moz.build
@@ -18,17 +18,16 @@ EXTRA_COMPONENTS += [
     'HelperAppDialog.js',
     'MailtoProtocolHandler.js',
     'OMAContentHandler.js',
     'PresentationRequestUIGlue.js',
     'ProcessGlobal.js',
     'SmsProtocolHandler.js',
     'SystemMessageInternal.js',
     'TelProtocolHandler.js',
-    'WebappsUpdateTimer.js',
 ]
 
 if CONFIG['OS_TARGET'] != 'Android':
     EXTRA_COMPONENTS += [
       'CommandLine.js',
       'OopCommandLine.js',
       'SimulatorScreen.js'
     ]
@@ -62,17 +61,16 @@ EXTRA_JS_MODULES += [
     'LogParser.jsm',
     'LogShake.jsm',
     'OrientationChangeHandler.jsm',
     'SafeMode.jsm',
     'Screenshot.jsm',
     'SignInToWebsite.jsm',
     'SystemAppProxy.jsm',
     'TelURIParser.jsm',
-    'WebappsUpdater.jsm',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
     EXTRA_JS_MODULES += [
       'GlobalSimulatorScreen.jsm'
     ]
 
 XPIDL_SOURCES += [
deleted file mode 100644
--- a/b2g/components/test/mochitest/app/client.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test app for bug 1171917</title>
-    <script type="application/javascript;version=1.7">
-
-function onLoad() {
-  navigator.serviceWorker.ready.then(() => {
-    parent.postMessage({status: "callback", data: "ready"}, "*");
-  });
-}
-
-    </script>
-  </head>
-  <body onload="onLoad()">
-  </body>
-</html>
deleted file mode 100644
--- a/b2g/components/test/mochitest/app/index.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <title>Test app for bug 1171917</title>
-    <script type="application/javascript;version=1.7">
-
-function ok(aCondition, aMessage) {
-  if (aCondition) {
-    alert("OK: " + aMessage);
-  } else {
-    alert("KO: " + aMessage);
-  }
-}
-
-function done() {
-  alert("DONE");
-}
-
-function testFrame(src) {
-  return new Promise((resolve) => {
-    var iframe = document.createElement("iframe");
-    iframe.src = src;
-    window.onmessage = function(e) {
-      if (e.data.status == "callback") {
-        window.onmessage = null;
-        var result = e.data.data;
-        document.body.removeChild(iframe);
-        iframe.src = "about:blank";
-        iframe = null;
-        resolve(result);
-      }
-    };
-    document.body.appendChild(iframe);
-  });
-}
-
-function registerServiceWorker() {
-  return navigator.serviceWorker.register("sw.sjs", {scope: "."});
-}
-
-function runTests() {
-  var lastSeenVersion;
-  return Promise.resolve()
-    .then(() => {
-      // Check whether the service worker is already registered and save its
-      // version.
-      return navigator.serviceWorker.getRegistration(".").then((swr) => {
-        if (!swr) {
-          lastSeenVersion = 0;
-          return registerServiceWorker();
-        }
-        return testFrame("version.html").then((body) => {
-          lastSeenVersion = parseInt(body);
-          return Promise.resolve();
-        });
-      });
-    })
-    .then(() => {
-      // Wait until the service worker starts controlling the client.
-      return testFrame("client.html");
-    })
-    .then(() => {
-      return new Promise((resolve) => {
-        testFrame("wait_for_update.html").then(() => {
-          // Fetch current version. It should be greater than the last seen version.
-          testFrame("version.html").then((body) => {
-            var currentVersion = parseInt(body);
-            ok(lastSeenVersion < currentVersion, "New service worker version seen");
-            resolve();
-          });
-        });
-      });
-    })
-    .then(done)
-    .catch((e) => {
-      dump("Unexpected error " + e);
-    });
-}
-
-    </script>
-  </head>
-  <body onload="runTests()">
-  </body>
-</html>
deleted file mode 100644
--- a/b2g/components/test/mochitest/app/manifest.webapp
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "name": "App",
-  "launch_path": "/index.html",
-  "description": "Test app for bug 1171917"
-}
deleted file mode 100644
--- a/b2g/components/test/mochitest/app/manifest.webapp^headers^
+++ /dev/null
@@ -1,1 +0,0 @@
-Content-Type: application/manifest+json
deleted file mode 100644
--- a/b2g/components/test/mochitest/app/sw.sjs
+++ /dev/null
@@ -1,28 +0,0 @@
-// The update process does not complete unless the service worker script changes.
-// The service worker script is a server-side JS file which allows us to get a
-// slightly different service worker script file each time the file is fetched.
-// Everytime there is either a registration or an update the script will be
-// fetched and a slightly different version of the script will be returned.
-
-function handleRequest(request, response) {
-  var stateName = request.scheme + "counter";
-  if (!getState(stateName)) {
-    setState(stateName, "1");
-  } else {
-    // Make sure that we pass a string value to setState!
-    setState(stateName, "" + (parseInt(getState(stateName)) + 1));
-  }
-  response.setHeader("Content-Type", "application/javascript", false);
-  response.write(getScript(stateName));
-}
-
-function getScript(stateName) {
-  return "oninstall = function(evt) {" +
-           "evt.waitUntil(self.skipWaiting());" +
-         "}; " +
-         "onfetch = function(evt) {" +
-           "if (evt.request.url.indexOf('get-sw-version') > -1) {" +
-             "evt.respondWith(new Response('" + getState(stateName) + "'));" +
-           "}" +
-         "};";
-}
deleted file mode 100644
--- a/b2g/components/test/mochitest/app/version.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test app for bug 1171917</title>
-    <script type="application/javascript;version=1.7">
-
-function onLoad() {
-  fetch("get-sw-version").then(function(r) {
-    return r.text();
-  }).then(function(body) {
-    parent.postMessage({status: "callback", data: body}, "*");
-  });
-}
-
-    </script>
-  </head>
-  <body onload="onLoad()">
-  </body>
-</html>
deleted file mode 100644
--- a/b2g/components/test/mochitest/app/wait_for_update.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <title>Test app for bug 1171917</title>
-    <script type="application/javascript;version=1.7">
-
-function update() {
-  alert("UPDATE");
-}
-
-function onLoad() {
-  navigator.serviceWorker.getRegistration(".").then(function(swr) {
-    swr.onupdatefound = function() {
-      swr.onupdatefound = null;
-      parent.postMessage({status: "callback", data: "done"}, "*");
-    };
-    update();
-  });
-}
-
-    </script>
-  </head>
-  <body onload="onLoad()">
-  </body>
-</html>
deleted file mode 100644
--- a/b2g/components/test/mochitest/chrome.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[DEFAULT]
-skip-if = toolkit != "gonk"
-support-files =
-  app/*
-
-[test_aboutserviceworkers.html]
--- a/b2g/components/test/mochitest/systemapp_helper.js
+++ b/b2g/components/test/mochitest/systemapp_helper.js
@@ -75,25 +75,16 @@ function listener(event) {
     next(); // call checkEventListening();
   } else {
     assert.ok(false, "Unexpected event of type " + event.type);
   }
 }
 
 
 var steps = [
-  function waitForWebapps() {
-    // We are using webapps API later in this test and we need to ensure
-    // it is fully initialized before trying to use it
-    let { DOMApplicationRegistry } =  Cu.import('resource://gre/modules/Webapps.jsm', {});
-    DOMApplicationRegistry.registryReady.then(function () {
-      next();
-    });
-  },
-
   function earlyEvents() {
     // Immediately try to send events
     SystemAppProxy._sendCustomEvent("mozChromeEvent", { name: "first" }, true);
     SystemAppProxy._sendCustomEvent("custom", { name: "second" }, true);
     next();
   },
 
   function createFrame() {
deleted file mode 100644
--- a/b2g/components/test/mochitest/test_aboutserviceworkers.html
+++ /dev/null
@@ -1,276 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1171917
-
-The tests being added here are about testing the logic underneath the
-about:serviceworkers panel in the settings app. That logic is a B2G dedicate
-component.
-The component let us update and unregister a Service Worker Registration. It
-communicates with content through content/chrome events. We mock them so we can
-send messages for updating/unregistering a particular Service Worker
-Registration.
-
-These tests install an app and the app registers a service worker. Through the
-component described above we update the corresponding Service Worker
-Registration, we test that the Service Worker gets updated and
-then we unregister it.
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 1171917</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-  <script type="application/javascript;version=1.7">
-    
-const ASW_CHROME_EVENT = "mozAboutServiceWorkersChromeEvent";
-const ASW_CONTENT_EVENT = "mozAboutServiceWorkersContentEvent";
-
-const { utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "AboutServiceWorkers",
-  "resource://gre/modules/AboutServiceWorkers.jsm");
-
-SimpleTest.waitForExplicitFinish();
-
-const gOrigin = "http://test/chrome/b2g/components/test/mochitest/app";
-const appManifestURL = gOrigin + "/manifest.webapp";
-let gApp;
-
-const ORIGINAL_INIT = AboutServiceWorkers.init;
-const ORIGINAL_SENDRESULT = AboutServiceWorkers.sendResult;
-const ORIGINAL_SENDERROR = AboutServiceWorkers.sendError;
-
-function debug(aMsg) {
-  dump("test_aboutserviceworkers.html - " + aMsg + "\n");
-}
-
-function mockInit() {
-  window.addEventListener(ASW_CONTENT_EVENT, AboutServiceWorkers);
-}
-
-function mockSendResult(aId, aResult) {
-  let result = {
-    detail: {
-      id: aId,
-      result: aResult
-    }
-  };
-  debug("mockSendResult, " + JSON.stringify(result));
-  let event = new CustomEvent(ASW_CHROME_EVENT, result);
-  window.dispatchEvent(event);
-}
-
-function mockSendError(aId, aError) {
-  let error = {
-    detail: {
-      id: aId,
-      error: aError
-    }
-  };
-  debug("mockSendError, " + JSON.stringify(error));
-  let event = new CustomEvent(ASW_CHROME_EVENT, error);
-  window.dispatchEvent(event);
-}
-
-function attachMocks() {
-  AboutServiceWorkers.init = mockInit;
-  AboutServiceWorkers.sendResult = mockSendResult;
-  AboutServiceWorkers.sendError = mockSendError;
-  return Promise.resolve();
-}
-
-function restoreMocks() {
-  AboutServiceWorkers.init = ORIGINAL_INIT;
-  AboutServiceWorkers.sendResult = ORIGINAL_SENDRESULT;
-  AboutServiceWorkers.sendError = ORIGINAL_SENDERROR;
-  return Promise.resolve();
-}
-
-function sendContentEvent(detail) {
-  let event = new CustomEvent(ASW_CONTENT_EVENT, {
-    detail: detail
-  });
-  window.dispatchEvent(event);
-}
-
-function chromeRequest(request) {
-  if (!request) {
-    return Promise.reject("InternalErrorMissingEventDetail");
-  }
-
-  return new Promise((resolve, reject) => {
-    let id = request.id;
-    window.addEventListener(ASW_CHROME_EVENT,
-                            function onChromeEvent(event) {
-      window.removeEventListener(ASW_CHROME_EVENT, onChromeEvent);
-      let message = event.detail;
-      if (!message || !message.id || message.id != id) {
-        return reject('InternalErrorWrongChromeEvent');
-      }
-
-      if (message.error) {
-        reject(message.error);
-      } else if (message.result) {
-        resolve(message.result);
-      }
-    });
-
-    sendContentEvent(request);
-  });
-}
-
-function uninstallApp() {
-  return new Promise((resolve, reject) => {
-    if (!gApp) {
-      return reject();
-    }
-    let req = navigator.mozApps.mgmt.uninstall(gApp);
-    req.onsuccess = resolve;
-    req.onerror = reject;
-  });
-}
-
-function update() {
-  return Promise.resolve()
-    .then(() => {
-      return chromeRequest({id: "0", name: "init"});
-    })
-    .then((result) => {
-      return chromeRequest({
-        id: "1",
-        name: "update",
-        principal: result.registrations[0].principal,
-        scope: result.registrations[0].scope
-      });
-    });
-}
-
-function testApp() {
-  if (!gApp) {
-    ok(false, "No test application to launch");
-    return Promise.reject();
-  }
-  return new Promise((resolve, reject) => {
-    let iframe = document.createElement("iframe");
-    let domParent = document.getElementById("container");
-    iframe.setAttribute("mozbrowser", "true");
-    iframe.setAttribute("mozapp", gApp.manifestURL);
-    iframe.addEventListener("mozbrowsershowmodalprompt", function listener(e) {
-      let message = e.detail.message;
-      if (/KO/.exec(message)) {
-        ok(false, "Message from app: " + message);
-      } else if (/OK/.exec(message)) {
-        ok(true, "Message from app: " + message);
-      } else if (/UPDATE/.exec(message)) {
-        ok(true, "Message from app: " + message);
-        update();
-      } else if (/DONE/.exec(message)) {
-        ok(true, "Message from app: " + message);
-        iframe.src = "about:blank";
-        domParent.removeChild(iframe);
-        iframe = null;
-        resolve();
-      }
-    }, false);
-    domParent.appendChild(iframe);
-    ok(true, "origin " +  gOrigin + gApp.manifest.launch_path);
-    SpecialPowers.wrap(iframe.contentWindow).location =
-      gOrigin + gApp.manifest.launch_path;
-  });
-}
-
-function installApp() {
-  return new Promise((resolve, reject) => {
-    let req = navigator.mozApps.install(appManifestURL);
-    req.onsuccess = function() {
-      gApp = req.result;
-      is(req.result.manifestURL, appManifestURL, "app installed");
-      if (req.result.installState == "installed") {
-        is(req.result.installState, "installed", "app downloaded");
-        resolve()
-      } else {
-        req.result.ondownloadapplied = function() {
-          is(req.result.installState, "installed", "app downloaded");
-          resolve();
-        }
-      }
-    }
-    req.onerror = reject;
-  });
-}
-
-function setup() {
-  info("Setting up");
-  return new Promise((resolve, reject) => {
-    SpecialPowers.pushPrefEnv({"set": [
-      ["dom.mozBrowserFramesEnabled", true],
-      ["dom.serviceWorkers.exemptFromPerDomainMax", true],
-      ["dom.serviceWorkers.enabled", true],
-      ["dom.serviceWorkers.testing.enabled", true],
-    ]}, () => {
-      SpecialPowers.pushPermissions([
-        { "type": "webapps-manage", "allow": 1, "context": document },
-        { "type": "browser", "allow": 1, "context": document },
-        { "type": "embed-apps", "allow": 1, "context": document }
-      ], () => {
-        SpecialPowers.autoConfirmAppInstall(() => {
-          SpecialPowers.autoConfirmAppUninstall(resolve);
-        });
-      });
-    });
-  });
-}
-
-function cleanUp() {
-  restoreMocks();
-  SimpleTest.finish();
-}
-
-function go() {
-  setup()
-    .then(attachMocks)
-    .then(() => {
-      AboutServiceWorkers.init();
-      return Promise.resolve();
-    })
-    .then(installApp)
-    .then(testApp)
-    .then(() => {
-      return chromeRequest({id: "2", name: "init"});
-    })
-    .then((result) => {
-      return chromeRequest({
-        id: "3",
-        name: "unregister",
-        principal: result.registrations[0].principal,
-        scope: result.registrations[0].scope
-      });
-    })
-    .then(() => {
-      return chromeRequest({id: "4", name: "init"});
-    })
-    .then((result) => {
-      ok(result.registrations && result.registrations.length === 0,
-         "Service worker registration was successfuly unregistered");
-    })
-    .then(uninstallApp)
-    .then(cleanUp)
-    .catch((e) => {
-      ok(false, "Unexpected error " + e);
-      cleanUp();
-    });
-}
-  </script>
-</head>
-<body onload="go()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1171917">Mozilla Bug 1171917</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-</pre>
-<div id="container"></div>
-</body>
-</html>
--- a/b2g/components/test/moz.build
+++ b/b2g/components/test/moz.build
@@ -1,9 +1,8 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
 MOCHITEST_MANIFESTS += ['mochitest/mochitest.ini']
-MOCHITEST_CHROME_MANIFESTS += ['mochitest/chrome.ini']
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -590,18 +590,16 @@
 @RESPATH@/components/servicesComponents.manifest
 @RESPATH@/components/cryptoComponents.manifest
 @RESPATH@/components/CaptivePortalDetectComponents.manifest
 @RESPATH@/components/captivedetect.js
 @RESPATH@/components/TelemetryStartup.js
 @RESPATH@/components/TelemetryStartup.manifest
 @RESPATH@/components/XULStore.js
 @RESPATH@/components/XULStore.manifest
-@RESPATH@/components/Webapps.js
-@RESPATH@/components/Webapps.manifest
 @RESPATH@/components/AppsService.js
 @RESPATH@/components/AppsService.manifest
 @RESPATH@/components/Push.js
 @RESPATH@/components/Push.manifest
 @RESPATH@/components/PushComponents.js
 
 @RESPATH@/components/nsDOMIdentity.js
 @RESPATH@/components/nsIDService.js
@@ -851,17 +849,16 @@ bin/libfreebl_32int64_3.so
 @RESPATH@/components/MarionetteComponents.manifest
 @RESPATH@/components/marionettecomponent.js
 #endif
 @RESPATH@/components/AlertsService.js
 @RESPATH@/components/ContentPermissionPrompt.js
 #ifdef MOZ_UPDATER
 @RESPATH@/components/UpdatePrompt.js
 #endif
-@RESPATH@/components/WebappsUpdateTimer.js
 @RESPATH@/components/DirectoryProvider.js
 @RESPATH@/components/ProcessGlobal.js
 @RESPATH@/components/OMAContentHandler.js
 @RESPATH@/components/RecoveryService.js
 @RESPATH@/components/MailtoProtocolHandler.js
 @RESPATH@/components/SmsProtocolHandler.js
 @RESPATH@/components/TelProtocolHandler.js
 @RESPATH@/components/B2GAboutRedirector.js
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1412,19 +1412,28 @@ var BookmarkingUI = {
       // Update the menu when a bookmark has been removed.
       // The native menubar on Mac doesn't support live update, so this won't
       // work there.
       this._populateRecentBookmarks(aHeaderItem, aExtraCSSClass);
     };
 
     let updatePlacesContextMenu = (shouldHidePrefUI = false) => {
       let prefEnabled = !shouldHidePrefUI && Services.prefs.getBoolPref(this.RECENTLY_BOOKMARKED_PREF);
-      document.getElementById("placesContext_showRecentlyBookmarked").hidden = shouldHidePrefUI || prefEnabled;
-      document.getElementById("placesContext_hideRecentlyBookmarked").hidden = shouldHidePrefUI || !prefEnabled;
-      document.getElementById("placesContext_recentlyBookmarkedSeparator").hidden = shouldHidePrefUI;
+      let showItem = document.getElementById("placesContext_showRecentlyBookmarked");
+      let hideItem = document.getElementById("placesContext_hideRecentlyBookmarked");
+      let separator = document.getElementById("placesContext_recentlyBookmarkedSeparator");
+      showItem.hidden = shouldHidePrefUI || prefEnabled;
+      hideItem.hidden = shouldHidePrefUI || !prefEnabled;
+      separator.hidden = shouldHidePrefUI;
+      if (!shouldHidePrefUI) {
+        // Move to the bottom of the menu.
+        separator.parentNode.appendChild(separator);
+        showItem.parentNode.appendChild(showItem);
+        hideItem.parentNode.appendChild(hideItem);
+      }
     };
 
     let onPlacesContextMenuShowing = event => {
       if (event.target == event.currentTarget) {
         let triggerPopup = event.target.triggerNode;
         while (triggerPopup && triggerPopup.localName != "menupopup") {
           triggerPopup = triggerPopup.parentNode;
         }
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -356,33 +356,30 @@
                               gContextMenu = null;
                               updateEditUIVisibility();">
 #include browser-context.inc
     </menupopup>
 
     <menupopup id="placesContext">
       <menuseparator id="placesContext_recentlyBookmarkedSeparator"
                      ignoreitem="true"
-                     ordinal="2"
                      hidden="true"/>
       <menuitem id="placesContext_hideRecentlyBookmarked"
                 label="&hideRecentlyBookmarked.label;"
                 accesskey="&hideRecentlyBookmarked.accesskey;"
                 oncommand="BookmarkingUI.hideRecentlyBookmarked();"
                 closemenu="single"
                 ignoreitem="true"
-                ordinal="2"
                 hidden="true"/>
       <menuitem id="placesContext_showRecentlyBookmarked"
                 label="&showRecentlyBookmarked.label;"
                 accesskey="&showRecentlyBookmarked.accesskey;"
                 oncommand="BookmarkingUI.showRecentlyBookmarked();"
                 closemenu="single"
                 ignoreitem="true"
-                ordinal="2"
                 hidden="true"/>
     </menupopup>
 
     <panel id="ctrlTab-panel" hidden="true" norestorefocus="true" level="top">
       <hbox>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -6448,17 +6448,17 @@
                     class="tab-background-end"/>
         </xul:hbox>
         <xul:hbox xbl:inherits="pinned,selected=visuallyselected,titlechanged,attention"
                   class="tab-content" align="center">
           <xul:image xbl:inherits="fadein,pinned,busy,progress,selected=visuallyselected"
                      class="tab-throbber"
                      role="presentation"
                      layer="true" />
-          <xul:image xbl:inherits="src=image,fadein,pinned,selected=visuallyselected,busy,crashed,sharing"
+          <xul:image xbl:inherits="src=image,loadingprincipal=iconLoadingPrincipal,fadein,pinned,selected=visuallyselected,busy,crashed,sharing"
                      anonid="tab-icon-image"
                      class="tab-icon-image"
                      validate="never"
                      role="presentation"/>
           <xul:image xbl:inherits="sharing,selected=visuallyselected"
                      anonid="sharing-icon"
                      class="tab-sharing-icon-overlay"
                      role="presentation"/>
--- a/browser/components/contextualidentity/test/browser/browser_favicon.js
+++ b/browser/components/contextualidentity/test/browser/browser_favicon.js
@@ -17,17 +17,17 @@ let gHttpServer = null;
 let gUserContextId;
 let gFaviconData;
 
 function getIconFile() {
   new Promise(resolve => {
     NetUtil.asyncFetch({
       uri: "http://www.example.com/browser/browser/components/contextualidentity/test/browser/favicon-normal32.png",
       loadUsingSystemPrincipal: true,
-      contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
+      contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE_FAVICON
     }, function(inputStream, status) {
         let size = inputStream.available();
         gFaviconData = NetUtil.readInputStreamToString(inputStream, size);
         resolve();
     });
   });
 }
 
--- a/browser/components/downloads/content/download.xml
+++ b/browser/components/downloads/content/download.xml
@@ -11,49 +11,53 @@
 <bindings id="downloadBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="download"
            extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
     <content orient="horizontal"
-             align="center"
              onclick="DownloadsView.onDownloadClick(event);">
-      <xul:stack>
-        <xul:image class="downloadTypeIcon"
-                   validate="always"
-                   xbl:inherits="src=image"/>
-        <xul:image class="downloadBlockedBadge" />
-      </xul:stack>
-      <xul:vbox pack="center"
+      <xul:hbox class="downloadMainArea"
                 flex="1"
-                class="downloadContainer"
-                style="width: &downloadDetails.width;">
-        <!-- We're letting localizers put a min-width in here primarily
-             because of the downloads summary at the bottom of the list of
-             download items. An element in the summary has the same min-width
-             on a description, and we don't want the panel to change size if the
-             summary isn't being displayed, so we ensure that items share the
-             same minimum width.
-             -->
-        <xul:description class="downloadTarget"
-                         crop="center"
-                         style="min-width: &downloadsSummary.minWidth2;"
-                         xbl:inherits="value=displayName,tooltiptext=displayName"/>
-        <xul:progressmeter anonid="progressmeter"
-                           class="downloadProgress"
-                           min="0"
-                           max="100"
-                           xbl:inherits="mode=progressmode,value=progress"/>
-        <xul:description class="downloadDetails"
-                         crop="end"
-                         xbl:inherits="value=status,tooltiptext=statusTip"/>
-      </xul:vbox>
-      <xul:stack>
+                align="center">
+        <xul:stack>
+          <xul:image class="downloadTypeIcon"
+                     validate="always"
+                     xbl:inherits="src=image"/>
+          <xul:image class="downloadBlockedBadge" />
+        </xul:stack>
+        <xul:vbox pack="center"
+                  flex="1"
+                  class="downloadContainer"
+                  style="width: &downloadDetails.width;">
+          <!-- We're letting localizers put a min-width in here primarily
+               because of the downloads summary at the bottom of the list of
+               download items. An element in the summary has the same min-width
+               on a description, and we don't want the panel to change size if the
+               summary isn't being displayed, so we ensure that items share the
+               same minimum width.
+               -->
+          <xul:description class="downloadTarget"
+                           crop="center"
+                           style="min-width: &downloadsSummary.minWidth2;"
+                           xbl:inherits="value=displayName,tooltiptext=displayName"/>
+          <xul:progressmeter anonid="progressmeter"
+                             class="downloadProgress"
+                             min="0"
+                             max="100"
+                             xbl:inherits="mode=progressmode,value=progress"/>
+          <xul:description class="downloadDetails"
+                           crop="end"
+                           xbl:inherits="value=status,tooltiptext=statusTip"/>
+        </xul:vbox>
+      </xul:hbox>
+      <xul:toolbarseparator />
+      <xul:stack class="downloadButtonArea">
         <xul:button class="downloadButton downloadCancel downloadIconCancel"
                     tooltiptext="&cmd.cancel.label;"
                     oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_cancel');"/>
         <xul:button class="downloadButton downloadRetry downloadIconRetry"
                     tooltiptext="&cmd.retry.label;"
                     oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_retry');"/>
         <xul:button class="downloadButton downloadShow downloadIconShow"
 #ifdef XP_MACOSX
--- a/browser/components/downloads/content/downloads.css
+++ b/browser/components/downloads/content/downloads.css
@@ -13,17 +13,18 @@ richlistitem[type="download"]:not([selec
   -moz-user-focus: none;
 }
 
 .downloadsHideDropmarker > #downloadsFooterButtonsSplitter,
 .downloadsHideDropmarker > #downloadsFooterDropmarker {
   display: none;
 }
 
-richlistitem[type="download"].download-state[state="1"]:not([exists]) .downloadShow {
+richlistitem[type="download"].download-state[state="1"]:not([exists]) > .downloadButtonArea,
+richlistitem[type="download"].download-state[state="1"]:not([exists]) > toolbarseparator {
   display: none;
 }
 
 #downloadsSummary:not([inprogress]) > vbox > #downloadsSummaryProgress,
 #downloadsSummary:not([inprogress]) > vbox > #downloadsSummaryDetails,
 #downloadsFooter:not([showingsummary]) #downloadsSummary {
   display: none;
 }
@@ -157,16 +158,21 @@ richlistitem.download button {
 
 .download-state:not(:-moz-any([state="2"], /* Failed             */
                               [state="3"]) /* Canceled           */)
                                            .downloadRetry,
 
 .download-state:not(          [state="1"]  /* Finished           */)
                                            .downloadShow,
 
+.download-state:-moz-any(     [state="6"], /* Blocked (parental) */
+                              [state="7"], /* Scanning           */
+                              [state="9"]) /* Blocked (policy)   */
+                                           > toolbarseparator,
+
 /* The "show blocked info" button is shown only in the downloads panel. */
 .downloadShowBlockedInfo
 {
   display: none;
 }
 
 /*** Downloads panel ***/
 
@@ -212,20 +218,17 @@ richlistitem.download button {
   transform: translateX(-101%);
 }
 
 /** When the subview is showing... **/
 
 /* Hide the buttons of all downloads except the one that triggered the
    subview. */
 #downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="subview"] .download-state:not([showingsubview]) .downloadButton {
-  display: none;
-}
-#downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="subview"] .download-state[showingsubview] .downloadButton {
-  display: inline;
+  visibility: hidden;
 }
 
 /* For the download that triggered the subview, move its button farther to the
    right by removing padding so that a minimum amount of the main view's right
    edge needs to be shown. */
 #downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="subview"] .download-state[showingsubview] {
   padding: 0;
 }
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -664,19 +664,16 @@ BrowserGlue.prototype = {
 
     // apply distribution customizations
     // prefs are applied in _onAppDefaults()
     this._distributionCustomizer.applyCustomizations();
 
     // handle any UI migration
     this._migrateUI();
 
-    // Evaluate Webapps.jsm early to resolve ts_paint regression bug 1256667.
-    Cu.import("resource://gre/modules/Webapps.jsm", {});
-
     PageThumbs.init();
     webrtcUI.init();
     AboutHome.init();
 
     DirectoryLinksProvider.init();
     NewTabUtils.init();
     NewTabUtils.links.addProvider(DirectoryLinksProvider);
     AboutNewTab.init();
--- a/browser/components/originattributes/test/browser/browser.ini
+++ b/browser/components/originattributes/test/browser/browser.ini
@@ -1,13 +1,19 @@
 [DEFAULT]
 skip-if = buildapp == "mulet"
 tags = usercontextid firstpartyisolation originattributes
 support-files =
   dummy.html
+  file_favicon.html
+  file_favicon.png
+  file_favicon.png^headers^
+  file_favicon_cache.html
+  file_favicon_cache.png
+  file_favicon_thirdParty.html
   file_firstPartyBasic.html
   file_sharedworker.html
   file_sharedworker.js
   head.js
   test.js
   test.js^headers^
   test.html
   test2.html
@@ -19,14 +25,16 @@ support-files =
   test_firstParty_http_redirect.html
   test_firstParty_http_redirect.html^headers^
   test_firstParty_iframe_http_redirect.html
   test_firstParty_postMessage.html
   window.html
   worker_blobify.js
   worker_deblobify.js
 
+[browser_favicon_firstParty.js]
+[browser_favicon_userContextId.js]
 [browser_firstPartyIsolation.js]
 [browser_localStorageIsolation.js]
 [browser_blobURLIsolation.js]
 [browser_imageCacheIsolation.js]
 [browser_sharedworker.js]
 [browser_httpauth.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/browser_favicon_firstParty.js
@@ -0,0 +1,340 @@
+/**
+ * Bug 1277803 - A test case for testing favicon loading across different first party domains.
+ */
+
+const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/PlacesUtils.jsm");
+
+const FIRST_PARTY_ONE = "example.com";
+const FIRST_PARTY_TWO = "example.org";
+const THIRD_PARTY = "mochi.test:8888";
+
+const TEST_SITE_ONE = "http://" + FIRST_PARTY_ONE;
+const TEST_SITE_TWO = "http://" + FIRST_PARTY_TWO;
+const THIRD_PARTY_SITE = "http://" + THIRD_PARTY;
+const TEST_DIRECTORY = "/browser/browser/components/originattributes/test/browser/";
+
+const TEST_PAGE = TEST_DIRECTORY + "file_favicon.html";
+const TEST_THIRD_PARTY_PAGE = TEST_DIRECTORY + "file_favicon_thirdParty.html";
+const TEST_CACHE_PAGE = TEST_DIRECTORY + "file_favicon_cache.html";
+
+const FAVICON_URI = TEST_DIRECTORY + "file_favicon.png";
+const TEST_FAVICON_CACHE_URI = TEST_DIRECTORY + "file_favicon_cache.png";
+
+let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
+let makeURI = Cu.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
+
+function clearAllImageCaches() {
+  let tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
+                             .getService(SpecialPowers.Ci.imgITools);
+  let imageCache = tools.getImgCacheForDocument(window.document);
+  imageCache.clearCache(true);  // true=chrome
+  imageCache.clearCache(false); // false=content
+}
+
+function clearAllPlacesFavicons() {
+  let faviconService = Cc["@mozilla.org/browser/favicon-service;1"]
+                          .getService(Ci.nsIFaviconService);
+
+  return new Promise(resolve => {
+    let observer = {
+      observe(aSubject, aTopic, aData) {
+        if (aTopic === "places-favicons-expired") {
+          resolve();
+          Services.obs.removeObserver(observer, "places-favicons-expired", false);
+        }
+      }
+    };
+
+    Services.obs.addObserver(observer, "places-favicons-expired", false);
+    faviconService.expireAllFavicons();
+  });
+}
+
+function observeFavicon(aFirstPartyDomain, aExpectedCookie, aPageURI) {
+  let faviconReqXUL = false;
+  let faviconReqPlaces = false;
+  let expectedPrincipal = Services.scriptSecurityManager
+                                  .createCodebasePrincipal(aPageURI, { firstPartyDomain: aFirstPartyDomain });
+
+  return new Promise(resolve => {
+    let observer = {
+      observe(aSubject, aTopic, aData) {
+        // Make sure that the topic is 'http-on-modify-request'.
+        if (aTopic === "http-on-modify-request") {
+          // We check the firstPartyDomain for the originAttributes of the loading
+          // channel. All requests for the favicon should contain the correct
+          // firstPartyDomain. There are two requests for a favicon loading, one
+          // from the Places library and one from the XUL image. The difference
+          // of them is the loading principal. The Places will use the content
+          // principal and the XUL image will use the system principal.
+
+          let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
+          let reqLoadInfo = httpChannel.loadInfo;
+          let loadingPrincipal = reqLoadInfo.loadingPrincipal;
+          let triggeringPrincipal = reqLoadInfo.triggeringPrincipal;
+
+          // Make sure this is a favicon request.
+          if (!httpChannel.URI.spec.endsWith(FAVICON_URI)) {
+            return;
+          }
+
+          // Check the first party domain.
+          is(reqLoadInfo.originAttributes.firstPartyDomain, aFirstPartyDomain,
+            "The loadInfo has correct first party domain");
+
+          if (loadingPrincipal.equals(systemPrincipal)) {
+            faviconReqXUL = true;
+            ok(triggeringPrincipal.equals(expectedPrincipal),
+              "The triggeringPrincipal of favicon loading from XUL should be the content principal.");
+          } else {
+            faviconReqPlaces = true;
+            ok(loadingPrincipal.equals(expectedPrincipal),
+              "The loadingPrincipal of favicon loading from Places should be the content prinicpal");
+          }
+
+          let faviconCookie = httpChannel.getRequestHeader("cookie");
+
+          is(faviconCookie, aExpectedCookie, "The cookie of the favicon loading is correct.");
+        } else {
+          ok(false, "Received unexpected topic: ", aTopic);
+        }
+
+        if (faviconReqXUL && faviconReqPlaces) {
+          Services.obs.removeObserver(observer, "http-on-modify-request", false);
+          resolve();
+        }
+      }
+    };
+
+    Services.obs.addObserver(observer, "http-on-modify-request", false);
+  });
+}
+
+function waitOnFaviconResponse(aFaviconURL) {
+  return new Promise(resolve => {
+    let observer = {
+      observe(aSubject, aTopic, aData) {
+        if (aTopic === "http-on-examine-response" ||
+            aTopic === "http-on-examine-cached-response") {
+
+          let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
+          let loadInfo = httpChannel.loadInfo;
+
+          if (httpChannel.URI.spec !== aFaviconURL) {
+            return;
+          }
+
+          let result = {
+            topic: aTopic,
+            firstPartyDomain: loadInfo.originAttributes.firstPartyDomain
+          };
+
+          resolve(result);
+          Services.obs.removeObserver(observer, "http-on-examine-response", false);
+          Services.obs.removeObserver(observer, "http-on-examine-cached-response", false);
+        }
+      }
+    };
+
+    Services.obs.addObserver(observer, "http-on-examine-response", false);
+    Services.obs.addObserver(observer, "http-on-examine-cached-response", false);
+  });
+}
+
+function waitOnFaviconLoaded(aFaviconURL) {
+  return new Promise(resolve => {
+    let observer = {
+      onPageChanged(uri, attr, value, id) {
+
+        if (attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
+            value === aFaviconURL) {
+          resolve();
+          PlacesUtils.history.removeObserver(observer, false);
+        }
+      },
+    };
+
+    PlacesUtils.history.addObserver(observer, false);
+  });
+}
+
+function* openTab(aURL) {
+  let tab = gBrowser.addTab(aURL);
+
+  // Select tab and make sure its browser is focused.
+  gBrowser.selectedTab = tab;
+  tab.ownerGlobal.focus();
+
+  let browser = gBrowser.getBrowserForTab(tab);
+  yield BrowserTestUtils.browserLoaded(browser);
+  return {tab, browser};
+}
+
+function* assignCookiesUnderFirstParty(aURL, aFirstParty, aCookieValue) {
+  // Open a tab under the given aFirstParty, and this tab will have an
+  // iframe which loads the aURL.
+  let tabInfo = yield openTabInFirstParty(aURL, aFirstParty);
+
+  // Add cookies into the iframe.
+  yield ContentTask.spawn(tabInfo.browser, aCookieValue, function* (value) {
+    content.document.cookie = value;
+  });
+
+  yield BrowserTestUtils.removeTab(tabInfo.tab);
+}
+
+function* generateCookies(aThirdParty) {
+  // we generate two different cookies for two first party domains.
+  let cookies = [];
+  cookies.push(Math.random().toString());
+  cookies.push(Math.random().toString());
+
+  let firstSiteURL;
+  let secondSiteURL;
+
+  if (aThirdParty) {
+    // Add cookies into the third party site with different first party domain.
+    firstSiteURL = THIRD_PARTY_SITE;
+    secondSiteURL = THIRD_PARTY_SITE;
+  } else {
+    // Add cookies into sites.
+    firstSiteURL = TEST_SITE_ONE;
+    secondSiteURL = TEST_SITE_TWO;
+  }
+
+  yield assignCookiesUnderFirstParty(firstSiteURL, TEST_SITE_ONE, cookies[0]);
+  yield assignCookiesUnderFirstParty(secondSiteURL, TEST_SITE_TWO, cookies[1]);
+
+  return cookies;
+}
+
+function* doTest(aTestPage, aExpectedCookies, aFaviconURL) {
+  let firstPageURI = makeURI(TEST_SITE_ONE + aTestPage);
+  let secondPageURI = makeURI(TEST_SITE_TWO + aTestPage);
+
+  // Start to observe the event of that favicon has been fully loaded.
+  let promiseFaviconLoaded = waitOnFaviconLoaded(aFaviconURL);
+
+  // Start to observe the favicon requests earlier in case we miss it.
+  let promiseObserveFavicon = observeFavicon(FIRST_PARTY_ONE, aExpectedCookies[0], firstPageURI);
+
+  // Open the tab for the first site.
+  let tabInfo = yield openTab(TEST_SITE_ONE + aTestPage);
+
+  // Waiting until favicon requests are all made.
+  yield promiseObserveFavicon;
+
+  // Waiting until favicon loaded.
+  yield promiseFaviconLoaded;
+
+  // Close the tab.
+  yield BrowserTestUtils.removeTab(tabInfo.tab);
+
+  // Start to observe the favicon requests earlier in case we miss it.
+  promiseObserveFavicon = observeFavicon(FIRST_PARTY_TWO, aExpectedCookies[1], secondPageURI);
+
+  // Open the tab for the second site.
+  tabInfo = yield openTab(TEST_SITE_TWO + aTestPage);
+
+  // Waiting until favicon requests are all made.
+  yield promiseObserveFavicon;
+
+  yield BrowserTestUtils.removeTab(tabInfo.tab);
+}
+
+add_task(function* setup() {
+  // Make sure first party isolation is enabled.
+  yield SpecialPowers.pushPrefEnv({"set": [
+      ["privacy.firstparty.isolate", true]
+  ]});
+});
+
+// A clean up function to prevent affecting other tests.
+registerCleanupFunction(() => {
+  // Clear all cookies.
+  let cookieMgr = Cc["@mozilla.org/cookiemanager;1"]
+                     .getService(Ci.nsICookieManager);
+  cookieMgr.removeAll();
+
+  // Clear all image caches and network caches.
+  clearAllImageCaches();
+
+  let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                        .getService(Ci.nsICacheStorageService);
+  networkCache.clear();
+});
+
+add_task(function* test_favicon_firstParty() {
+  for (let testThirdParty of [false, true]) {
+    // Clear all image caches and network caches before running the test.
+    clearAllImageCaches();
+
+    let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                        .getService(Ci.nsICacheStorageService);
+    networkCache.clear();
+
+    // Clear Places favicon caches.
+    yield clearAllPlacesFavicons();
+
+    let cookies = yield generateCookies(testThirdParty);
+
+    if (testThirdParty) {
+      yield doTest(TEST_THIRD_PARTY_PAGE, cookies, THIRD_PARTY_SITE + FAVICON_URI);
+    } else {
+      yield doTest(TEST_PAGE, cookies, TEST_SITE_ONE + FAVICON_URI);
+    }
+  }
+});
+
+add_task(function* test_favicon_cache_firstParty() {
+  // Clear all image caches and network caches before running the test.
+  clearAllImageCaches();
+
+  let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                        .getService(Ci.nsICacheStorageService);
+  networkCache.clear();
+
+  // Open the tab for the first site.
+  let tabInfoA = yield openTab(TEST_SITE_ONE + TEST_CACHE_PAGE);
+
+  // Start to observer the event of that favicon has been fully loaded and cached.
+  let promiseForFaviconLoaded = waitOnFaviconLoaded(THIRD_PARTY_SITE + TEST_FAVICON_CACHE_URI);
+
+  // Wait for the favicon response of the first tab.
+  let response = yield waitOnFaviconResponse(THIRD_PARTY_SITE + TEST_FAVICON_CACHE_URI);
+
+  // Make sure the favicon is loaded through the network and its first party domain is correct.
+  is(response.topic, "http-on-examine-response", "The favicon image should be loaded through network.");
+  is(response.firstPartyDomain, FIRST_PARTY_ONE, "We should only observe the network response for the first first party.");
+
+  // Waiting until the favicon has been loaded and cached.
+  yield promiseForFaviconLoaded;
+
+  // Open the tab again for checking the image cache is working correctly.
+  let tabInfoB = yield openTab(TEST_SITE_ONE + TEST_CACHE_PAGE);
+
+  // Start to observe the favicon response, the second tab actually will not
+  // make any network request since the favicon will be loaded by the cache for
+  // both Places and XUL image. So here, we are going to observe the favicon
+  // response for the third tab which opens with the second first party.
+  let promiseForFaviconResponse = waitOnFaviconResponse(THIRD_PARTY_SITE + TEST_FAVICON_CACHE_URI);
+
+  // Open the tab for the second site.
+  let tabInfoC = yield openTab(TEST_SITE_TWO + TEST_CACHE_PAGE);
+
+  // Wait for the favicon response. In this case, we suppose to catch the
+  // response for the third tab but not the second tab since it will not
+  // go through the network.
+  response = yield promiseForFaviconResponse;
+
+  // Check that the favicon response has came from the network and it has the
+  // correct first party domain.
+  is(response.topic, "http-on-examine-response", "The favicon image should be loaded through network again.");
+  is(response.firstPartyDomain, FIRST_PARTY_TWO, "We should only observe the network response for the second first party.");
+
+  yield BrowserTestUtils.removeTab(tabInfoA.tab);
+  yield BrowserTestUtils.removeTab(tabInfoB.tab);
+  yield BrowserTestUtils.removeTab(tabInfoC.tab);
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/browser_favicon_userContextId.js
@@ -0,0 +1,250 @@
+/**
+ * Bug 1277803 - A test caes for testing favicon loading across different userContextId.
+ */
+
+const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
+
+XPCOMUtils.defineLazyModuleGetter(this, "Promise",
+  "resource://gre/modules/Promise.jsm");
+
+const TEST_SITE = "http://mochi.test:8888";
+
+const TEST_PAGE = TEST_SITE + "/browser/browser/components/originattributes/" +
+                  "test/browser/file_favicon.html";
+const FAVICON_URI = TEST_SITE + "/browser/browser/components/originattributes/" +
+                    "test/browser/file_favicon.png";
+const TEST_THIRD_PARTY_PAGE = "http://example.com/browser/browser/components/" +
+                              "originattributes/test/browser/file_favicon_thirdParty.html";
+
+const USER_CONTEXT_ID_PERSONAL = 1;
+const USER_CONTEXT_ID_WORK     = 2;
+
+let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
+let makeURI = Cu.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
+
+function clearAllImageCaches() {
+  var tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
+                             .getService(SpecialPowers.Ci.imgITools);
+  var imageCache = tools.getImgCacheForDocument(window.document);
+  imageCache.clearCache(true);  // true=chrome
+  imageCache.clearCache(false); // false=content
+}
+
+function clearAllPlacesFavicons() {
+  let faviconService = Cc["@mozilla.org/browser/favicon-service;1"]
+                          .getService(Ci.nsIFaviconService);
+
+  return new Promise(resolve => {
+    let observer = {
+      observe(aSubject, aTopic, aData) {
+        if (aTopic === "places-favicons-expired") {
+          resolve();
+          Services.obs.removeObserver(observer, "places-favicons-expired", false);
+        }
+      }
+    };
+
+    Services.obs.addObserver(observer, "places-favicons-expired", false);
+    faviconService.expireAllFavicons();
+  });
+}
+
+function FaviconObserver(aUserContextId, aExpectedCookie, aPageURI) {
+  this.reset(aUserContextId, aExpectedCookie, aPageURI);
+}
+
+FaviconObserver.prototype = {
+  observe(aSubject, aTopic, aData) {
+    // Make sure that the topic is 'http-on-modify-request'.
+    if (aTopic === "http-on-modify-request") {
+      // We check the userContextId for the originAttributes of the loading
+      // channel. All requests for the favicon should contain the correct
+      // userContextId. There are two requests for a favicon loading, one
+      // from the Places library and one from the XUL image. The difference
+      // of them is the loading principal. The Places will use the content
+      // principal and the XUL image will use the system principal.
+
+      let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
+      let reqLoadInfo = httpChannel.loadInfo;
+      let loadingPrincipal;
+      let triggeringPrincipal;
+
+      // Make sure this is a favicon request.
+      if (httpChannel.URI.spec !== FAVICON_URI) {
+        return;
+      }
+
+      if (reqLoadInfo) {
+        loadingPrincipal = reqLoadInfo.loadingPrincipal;
+        triggeringPrincipal = reqLoadInfo.triggeringPrincipal;
+      }
+
+      // Check the userContextId.
+      is(reqLoadInfo.originAttributes.userContextId, this._curUserContextId,
+        "The loadInfo has correct userContextId");
+
+      if (loadingPrincipal.equals(systemPrincipal)) {
+        this._faviconReqXUL = true;
+        ok(triggeringPrincipal.equals(this._expectedPrincipal),
+          "The triggeringPrincipal of favicon loading from XUL should be the content principal.");
+      } else {
+        this._faviconReqPlaces = true;
+        ok(loadingPrincipal.equals(this._expectedPrincipal),
+          "The loadingPrincipal of favicon loading from Places should be the content prinicpal");
+      }
+
+      let faviconCookie = httpChannel.getRequestHeader("cookie");
+
+      is(faviconCookie, this._expectedCookie, "The cookie of the favicon loading is correct.");
+    } else {
+      ok(false, "Received unexpected topic: ", aTopic);
+    }
+
+    if (this._faviconReqXUL && this._faviconReqPlaces) {
+      this._faviconLoaded.resolve();
+    }
+  },
+
+  reset(aUserContextId, aExpectedCookie, aPageURI) {
+    this._curUserContextId = aUserContextId;
+    this._expectedCookie = aExpectedCookie;
+    this._expectedPrincipal = Services.scriptSecurityManager
+                                      .createCodebasePrincipal(aPageURI, { userContextId: aUserContextId });
+    this._faviconReqXUL = false;
+    this._faviconReqPlaces = false;
+    this._faviconLoaded = new Promise.defer();
+  },
+
+  get promise() {
+    return this._faviconLoaded.promise;
+  }
+};
+
+function waitOnFaviconLoaded(aFaviconURL) {
+  return new Promise(resolve => {
+    let observer = {
+      onPageChanged(uri, attr, value, id) {
+
+        if (attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
+            value === aFaviconURL) {
+          resolve();
+          PlacesUtils.history.removeObserver(observer, false);
+        }
+      },
+    };
+
+    PlacesUtils.history.addObserver(observer, false);
+  });
+}
+
+function* generateCookies() {
+  // we generate two different cookies for two userContextIds.
+  let cookies = [];
+  cookies.push(Math.random().toString());
+  cookies.push(Math.random().toString());
+
+  // Then, we add cookies into the site for 'personal' and 'work'.
+  let tabInfoA = yield openTabInUserContext(TEST_SITE, USER_CONTEXT_ID_PERSONAL);
+  let tabInfoB = yield openTabInUserContext(TEST_SITE, USER_CONTEXT_ID_WORK);
+
+  yield ContentTask.spawn(tabInfoA.browser, cookies[0], function* (value) {
+    content.document.cookie = value;
+  });
+
+  yield ContentTask.spawn(tabInfoB.browser, cookies[1], function* (value) {
+    content.document.cookie = value;
+  });
+
+  yield BrowserTestUtils.removeTab(tabInfoA.tab);
+  yield BrowserTestUtils.removeTab(tabInfoB.tab);
+
+  return cookies;
+}
+
+function* doTest(aTestPage) {
+  let cookies = yield generateCookies();
+  let pageURI = makeURI(aTestPage);
+
+  // Create the observer object for observing request channels of the personal
+  // container.
+  let observer = new FaviconObserver(USER_CONTEXT_ID_PERSONAL, cookies[0], pageURI);
+
+  Services.obs.addObserver(observer, "http-on-modify-request", false);
+
+  // Open the tab with the personal container.
+  let tabInfo = yield openTabInUserContext(aTestPage, USER_CONTEXT_ID_PERSONAL);
+
+  // Waiting for favicon requests are all made.
+  yield observer.promise;
+  // Waiting for favicon loaded.
+  yield waitOnFaviconLoaded(FAVICON_URI);
+
+  // Close the tab.
+  yield BrowserTestUtils.removeTab(tabInfo.tab);
+
+  // Reset the observer for observing requests for the work container.
+  observer.reset(USER_CONTEXT_ID_WORK, cookies[1], pageURI);
+  tabInfo = yield openTabInUserContext(aTestPage, USER_CONTEXT_ID_WORK);
+
+  // Waiting for favicon requests are all made.
+  yield observer.promise;
+
+  Services.obs.removeObserver(observer, "http-on-modify-request", false);
+
+  yield BrowserTestUtils.removeTab(tabInfo.tab);
+}
+
+add_task(function* setup() {
+  // Make sure userContext is enabled.
+  yield SpecialPowers.pushPrefEnv({"set": [
+      ["privacy.userContext.enabled", true]
+  ]});
+});
+
+// A clean up function to prevent affecting other tests.
+registerCleanupFunction(() => {
+  // Clear all cookies.
+  let cookieMgr = Cc["@mozilla.org/cookiemanager;1"]
+                     .getService(Ci.nsICookieManager);
+  cookieMgr.removeAll();
+
+  // Clear all image caches and network caches.
+  clearAllImageCaches();
+
+  let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                        .getService(Ci.nsICacheStorageService);
+  networkCache.clear();
+
+  // Clear Places favicon caches.
+  clearAllPlacesFavicons();
+});
+
+add_task(function* test_favicon_userContextId() {
+  // Clear all image caches before running the test.
+  clearAllImageCaches();
+
+  // Clear all network caches.
+  let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                        .getService(Ci.nsICacheStorageService);
+  networkCache.clear();
+
+  // Clear Places favicon caches.
+  yield clearAllPlacesFavicons();
+
+  yield doTest(TEST_PAGE);
+});
+
+add_task(function* test_thirdPartyFavicon_userContextId() {
+  // Clear all image caches before running the test.
+  clearAllImageCaches();
+
+  // Clear all network caches.
+  let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                        .getService(Ci.nsICacheStorageService);
+  networkCache.clear();
+
+  // Clear Places favicon caches.
+  yield clearAllPlacesFavicons();
+
+  yield doTest(TEST_THIRD_PARTY_PAGE);
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/file_favicon.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <title>Favicon Test for originAttributes</title>
+    <link rel="icon" type="image/png" href="file_favicon.png" />
+  </head>
+  <body>
+    Favicon!!
+  </body>
+</html>
\ No newline at end of file
new file mode 100644
index 0000000000000000000000000000000000000000..5535363c94df7314765551f65311ec6f98729d8e
GIT binary patch
literal 344
zc$@)P0jK_nP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80003WNkl<ZSi@ud
z|NsAgh5-aj3<C^C9l%0R#sBwE#yKee29*B}N^?LcMg=I}1WL<7#aV`G2>ibbr58i#
zeNc((P#P98>`-}V2r!yL=>({_1(eS*I75IDqa1+6`Tu4pJs&FZfkdNSpkC~N^7XN%
ziNTl#4nlptmQ0_+z#gbM8_{x!@L&&t|69@WIcn7X|AQkj;gW}$#~3qYLI76MeMc4k
zL!iLKDUaQ}p<fv>vJfohhiYxer~!@C3s8YCB*r;9fSSj^Ib=e>8|uYfC?P<0IRG;c
zE&mVZy1*Xl@?ezO@c*9=cpEsFAp@-q8U3Mr{vneF1fh&<D9wk`BKrRaM~jF7M~jF-
q8*kfi5VnX$TC13Gv~M`#9RL8-wO_*zBf!o80000<MNUMnLSTX;M3C|T
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/file_favicon.png^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-cache
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/file_favicon_cache.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <title>Favicon Test for originAttributes</title>
+    <link rel="icon" type="image/png" href="http://mochi.test:8888/browser/browser/components/originattributes/test/browser/file_favicon_cache.png" />
+  </head>
+  <body>
+    Third Party Favicon!!
+  </body>
+</html>
\ No newline at end of file
new file mode 100644
index 0000000000000000000000000000000000000000..5535363c94df7314765551f65311ec6f98729d8e
GIT binary patch
literal 344
zc$@)P0jK_nP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80003WNkl<ZSi@ud
z|NsAgh5-aj3<C^C9l%0R#sBwE#yKee29*B}N^?LcMg=I}1WL<7#aV`G2>ibbr58i#
zeNc((P#P98>`-}V2r!yL=>({_1(eS*I75IDqa1+6`Tu4pJs&FZfkdNSpkC~N^7XN%
ziNTl#4nlptmQ0_+z#gbM8_{x!@L&&t|69@WIcn7X|AQkj;gW}$#~3qYLI76MeMc4k
zL!iLKDUaQ}p<fv>vJfohhiYxer~!@C3s8YCB*r;9fSSj^Ib=e>8|uYfC?P<0IRG;c
zE&mVZy1*Xl@?ezO@c*9=cpEsFAp@-q8U3Mr{vneF1fh&<D9wk`BKrRaM~jF7M~jF-
q8*kfi5VnX$TC13Gv~M`#9RL8-wO_*zBf!o80000<MNUMnLSTX;M3C|T
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/file_favicon_thirdParty.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <title>Favicon Test for originAttributes</title>
+    <link rel="icon" type="image/png" href="http://mochi.test:8888/browser/browser/components/originattributes/test/browser/file_favicon.png" />
+  </head>
+  <body>
+    Third Party Favicon!!
+  </body>
+</html>
\ No newline at end of file
--- a/browser/components/privatebrowsing/test/browser/browser.ini
+++ b/browser/components/privatebrowsing/test/browser/browser.ini
@@ -10,30 +10,34 @@ support-files =
   browser_privatebrowsing_localStorage_page2.html
   browser_privatebrowsing_placesTitleNoUpdate.html
   browser_privatebrowsing_protocolhandler_page.html
   browser_privatebrowsing_windowtitle_page.html
   head.js
   popup.html
   title.sjs
   empty_file.html
+  file_favicon.html
+  file_favicon.png
+  file_favicon.png^headers^
 
 [browser_privatebrowsing_DownloadLastDirWithCPS.js]
 [browser_privatebrowsing_about.js]
 tags = trackingprotection
 [browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js]
 [browser_privatebrowsing_aboutSessionRestore.js]
 [browser_privatebrowsing_cache.js]
 [browser_privatebrowsing_certexceptionsui.js]
 [browser_privatebrowsing_concurrent.js]
 [browser_privatebrowsing_context_and_chromeFlags.js]
 [browser_privatebrowsing_crh.js]
 [browser_privatebrowsing_downloadLastDir.js]
 [browser_privatebrowsing_downloadLastDir_c.js]
 [browser_privatebrowsing_downloadLastDir_toggle.js]
+[browser_privatebrowsing_favicon.js]
 [browser_privatebrowsing_geoprompt.js]
 [browser_privatebrowsing_lastpbcontextexited.js]
 [browser_privatebrowsing_localStorage.js]
 [browser_privatebrowsing_localStorage_before_after.js]
 [browser_privatebrowsing_noSessionRestoreMenuOption.js]
 [browser_privatebrowsing_nonbrowser.js]
 [browser_privatebrowsing_opendir.js]
 [browser_privatebrowsing_placesTitleNoUpdate.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_favicon.js
@@ -0,0 +1,293 @@
+/* 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/. */
+
+// This test make sure that the favicon of the private browsing is isolated.
+
+const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
+
+const TEST_SITE = "http://mochi.test:8888";
+const TEST_CACHE_SITE = "http://www.example.com";
+const TEST_DIRECTORY = "/browser/browser/components/privatebrowsing/test/browser/";
+
+const TEST_PAGE = TEST_SITE + TEST_DIRECTORY + "file_favicon.html";
+const TEST_CACHE_PAGE = TEST_CACHE_SITE + TEST_DIRECTORY + "file_favicon.html";
+const FAVICON_URI = TEST_SITE + TEST_DIRECTORY + "file_favicon.png";
+const FAVICON_CACHE_URI = TEST_CACHE_SITE + TEST_DIRECTORY + "file_favicon.png";
+
+let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
+let makeURI = Cu.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
+
+function clearAllImageCaches() {
+  let tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
+                             .getService(SpecialPowers.Ci.imgITools);
+  let imageCache = tools.getImgCacheForDocument(window.document);
+  imageCache.clearCache(true);  // true=chrome
+  imageCache.clearCache(false); // false=content
+}
+
+function clearAllPlacesFavicons() {
+  let faviconService = Cc["@mozilla.org/browser/favicon-service;1"]
+                          .getService(Ci.nsIFaviconService);
+
+  return new Promise(resolve => {
+    let observer = {
+      observe(aSubject, aTopic, aData) {
+        if (aTopic === "places-favicons-expired") {
+          resolve();
+          Services.obs.removeObserver(observer, "places-favicons-expired", false);
+        }
+      }
+    };
+
+    Services.obs.addObserver(observer, "places-favicons-expired", false);
+    faviconService.expireAllFavicons();
+  });
+}
+
+function observeFavicon(aIsPrivate, aExpectedCookie, aPageURI) {
+  let faviconReqXUL = false;
+  let faviconReqPlaces = false;
+  let attr = {};
+
+  if (aIsPrivate) {
+    attr.privateBrowsingId = 1;
+  }
+
+  let expectedPrincipal = Services.scriptSecurityManager
+                                  .createCodebasePrincipal(aPageURI, attr);
+
+  return new Promise(resolve => {
+    let observer = {
+      observe(aSubject, aTopic, aData) {
+        // Make sure that the topic is 'http-on-modify-request'.
+        if (aTopic === "http-on-modify-request") {
+          // We check the privateBrowsingId for the originAttributes of the loading
+          // channel. All requests for the favicon should contain the correct
+          // privateBrowsingId. There are two requests for a favicon loading, one
+          // from the Places library and one from the XUL image. The difference
+          // of them is the loading principal. The Places will use the content
+          // principal and the XUL image will use the system principal.
+
+          let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
+          let reqLoadInfo = httpChannel.loadInfo;
+          let loadingPrincipal = reqLoadInfo.loadingPrincipal;
+          let triggeringPrincipal = reqLoadInfo.triggeringPrincipal;
+
+          // Make sure this is a favicon request.
+          if (httpChannel.URI.spec !== FAVICON_URI) {
+            return;
+          }
+
+          // Check the privateBrowsingId.
+          if (aIsPrivate) {
+            is(reqLoadInfo.originAttributes.privateBrowsingId, 1, "The loadInfo has correct privateBrowsingId");
+          } else {
+            is(reqLoadInfo.originAttributes.privateBrowsingId, 0, "The loadInfo has correct privateBrowsingId");
+          }
+
+          if (loadingPrincipal.equals(systemPrincipal)) {
+            faviconReqXUL = true;
+            ok(triggeringPrincipal.equals(expectedPrincipal),
+              "The triggeringPrincipal of favicon loading from XUL should be the content principal.");
+          } else {
+            faviconReqPlaces = true;
+            ok(loadingPrincipal.equals(expectedPrincipal),
+              "The loadingPrincipal of favicon loading from Places should be the content prinicpal");
+          }
+
+          let faviconCookie = httpChannel.getRequestHeader("cookie");
+
+          is(faviconCookie, aExpectedCookie, "The cookie of the favicon loading is correct.");
+        } else {
+          ok(false, "Received unexpected topic: ", aTopic);
+        }
+
+        if (faviconReqXUL && faviconReqPlaces) {
+          resolve();
+          Services.obs.removeObserver(observer, "http-on-modify-request", false);
+        }
+      }
+    };
+
+    Services.obs.addObserver(observer, "http-on-modify-request", false);
+  });
+}
+
+function waitOnFaviconResponse(aFaviconURL) {
+  return new Promise(resolve => {
+    let observer = {
+      observe(aSubject, aTopic, aData) {
+        if (aTopic === "http-on-examine-response" ||
+            aTopic === "http-on-examine-cached-response") {
+
+          let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
+          let loadInfo = httpChannel.loadInfo;
+
+          if (httpChannel.URI.spec !== aFaviconURL) {
+            return;
+          }
+
+          let result = {
+            topic: aTopic,
+            privateBrowsingId: loadInfo.originAttributes.privateBrowsingId
+          };
+
+          resolve(result);
+          Services.obs.removeObserver(observer, "http-on-examine-response", false);
+          Services.obs.removeObserver(observer, "http-on-examine-cached-response", false);
+        }
+      }
+    };
+
+    Services.obs.addObserver(observer, "http-on-examine-response", false);
+    Services.obs.addObserver(observer, "http-on-examine-cached-response", false);
+  });
+}
+
+function waitOnFaviconLoaded(aFaviconURL) {
+  return new Promise(resolve => {
+    let observer = {
+      onPageChanged(uri, attr, value, id) {
+
+        if (attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
+            value === aFaviconURL) {
+          resolve();
+          PlacesUtils.history.removeObserver(observer, false);
+        }
+      },
+    };
+
+    PlacesUtils.history.addObserver(observer, false);
+  });
+}
+
+function* assignCookies(aBrowser, aURL, aCookieValue){
+  let tabInfo = yield openTab(aBrowser, aURL);
+
+  yield ContentTask.spawn(tabInfo.browser, aCookieValue, function* (value) {
+    content.document.cookie = value;
+  });
+
+  yield BrowserTestUtils.removeTab(tabInfo.tab);
+}
+
+function* openTab(aBrowser, aURL) {
+  let tab = aBrowser.addTab(aURL);
+
+  // Select tab and make sure its browser is focused.
+  aBrowser.selectedTab = tab;
+  tab.ownerGlobal.focus();
+
+  let browser = aBrowser.getBrowserForTab(tab);
+  yield BrowserTestUtils.browserLoaded(browser);
+  return {tab, browser};
+}
+
+// A clean up function to prevent affecting other tests.
+registerCleanupFunction(() => {
+  // Clear all cookies.
+  let cookieMgr = Cc["@mozilla.org/cookiemanager;1"]
+                     .getService(Ci.nsICookieManager);
+  cookieMgr.removeAll();
+
+  // Clear all image caches and network caches.
+  clearAllImageCaches();
+
+  let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                        .getService(Ci.nsICacheStorageService);
+  networkCache.clear();
+});
+
+add_task(function* test_favicon_privateBrowsing() {
+  // Clear all image caches before running the test.
+  clearAllImageCaches();
+
+  // Clear all favicons in Places.
+  yield clearAllPlacesFavicons();
+
+  // Create a private browsing window.
+  let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+  let pageURI = makeURI(TEST_PAGE);
+
+  // Generate two random cookies for non-private window and private window
+  // respectively.
+  let cookies = [];
+  cookies.push(Math.random().toString());
+  cookies.push(Math.random().toString());
+
+  // Open a tab in private window and add a cookie into it.
+  yield assignCookies(privateWindow.gBrowser, TEST_SITE, cookies[0]);
+
+  // Open a tab in non-private window and add a cookie into it.
+  yield assignCookies(gBrowser, TEST_SITE, cookies[1]);
+
+  // Add the observer earlier in case we don't capture events in time.
+  let promiseObserveFavicon = observeFavicon(true, cookies[0], pageURI);
+
+  // Open a tab for the private window.
+  let tabInfo = yield openTab(privateWindow.gBrowser, TEST_PAGE);
+
+  // Waiting until favicon requests are all made.
+  yield promiseObserveFavicon;
+
+  // Close the tab.
+  yield BrowserTestUtils.removeTab(tabInfo.tab);
+
+  // Add the observer earlier in case we don't capture events in time.
+  promiseObserveFavicon = observeFavicon(false, cookies[1], pageURI);
+
+  // Open a tab for the non-private window.
+  tabInfo = yield openTab(gBrowser, TEST_PAGE);
+
+  // Waiting until favicon requests are all made.
+  yield promiseObserveFavicon;
+
+  // Close the tab.
+  yield BrowserTestUtils.removeTab(tabInfo.tab);
+  yield BrowserTestUtils.closeWindow(privateWindow);
+});
+
+add_task(function* test_favicon_cache_privateBrowsing() {
+  // Clear all image cahces and network cache before running the test.
+  clearAllImageCaches();
+
+  let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                        .getService(Ci.nsICacheStorageService);
+  networkCache.clear();
+
+  // Clear all favicons in Places.
+  yield clearAllPlacesFavicons();
+
+  // Add an observer for making sure the favicon has been loaded and cached.
+  let promiseFaviconLoaded = waitOnFaviconLoaded(FAVICON_CACHE_URI);
+
+  // Open a tab for the non-private window.
+  let tabInfoNonPrivate = yield openTab(gBrowser, TEST_CACHE_PAGE);
+
+  let response = yield waitOnFaviconResponse(FAVICON_CACHE_URI);
+
+  yield promiseFaviconLoaded;
+
+  // Check that the favicon response has come from the network and it has the
+  // correct privateBrowsingId.
+  is(response.topic, "http-on-examine-response", "The favicon image should be loaded through network.");
+  is(response.privateBrowsingId, 0, "We should observe the network response for the non-private tab.");
+
+  // Create a private browsing window.
+  let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+
+  // Open a tab for the private window.
+  let tabInfoPrivate = yield openTab(privateWindow.gBrowser, TEST_CACHE_PAGE);
+
+  // Wait for the favicon response of the private tab.
+  response = yield waitOnFaviconResponse(FAVICON_CACHE_URI);
+
+  // Make sure the favicon is loaded through the network and its privateBrowsingId is correct.
+  is(response.topic, "http-on-examine-response", "The favicon image should be loaded through the network again.");
+  is(response.privateBrowsingId, 1, "We should observe the network response for the private tab.");
+
+  yield BrowserTestUtils.removeTab(tabInfoPrivate.tab);
+  yield BrowserTestUtils.removeTab(tabInfoNonPrivate.tab);
+  yield BrowserTestUtils.closeWindow(privateWindow);
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/file_favicon.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <title>Favicon Test for originAttributes</title>
+    <link rel="icon" type="image/png" href="file_favicon.png" />
+  </head>
+  <body>
+    Favicon!!
+  </body>
+</html>
\ No newline at end of file
new file mode 100644
index 0000000000000000000000000000000000000000..5535363c94df7314765551f65311ec6f98729d8e
GIT binary patch
literal 344
zc$@)P0jK_nP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80003WNkl<ZSi@ud
z|NsAgh5-aj3<C^C9l%0R#sBwE#yKee29*B}N^?LcMg=I}1WL<7#aV`G2>ibbr58i#
zeNc((P#P98>`-}V2r!yL=>({_1(eS*I75IDqa1+6`Tu4pJs&FZfkdNSpkC~N^7XN%
ziNTl#4nlptmQ0_+z#gbM8_{x!@L&&t|69@WIcn7X|AQkj;gW}$#~3qYLI76MeMc4k
zL!iLKDUaQ}p<fv>vJfohhiYxer~!@C3s8YCB*r;9fSSj^Ib=e>8|uYfC?P<0IRG;c
zE&mVZy1*Xl@?ezO@c*9=cpEsFAp@-q8U3Mr{vneF1fh&<D9wk`BKrRaM~jF7M~jF-
q8*kfi5VnX$TC13Gv~M`#9RL8-wO_*zBf!o80000<MNUMnLSTX;M3C|T
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/file_favicon.png^headers^
@@ -0,0 +1,1 @@
+Cache-Control: no-cache
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -506,18 +506,16 @@
 @RESPATH@/components/TelemetryStartup.js
 @RESPATH@/components/TelemetryStartup.manifest
 @RESPATH@/components/XULStore.js
 @RESPATH@/components/XULStore.manifest
 @RESPATH@/components/messageWakeupService.js
 @RESPATH@/components/messageWakeupService.manifest
 @RESPATH@/components/SettingsManager.js
 @RESPATH@/components/SettingsManager.manifest
-@RESPATH@/components/Webapps.js
-@RESPATH@/components/Webapps.manifest
 @RESPATH@/components/AppsService.js
 @RESPATH@/components/AppsService.manifest
 @RESPATH@/components/recording-cmdline.js
 @RESPATH@/components/recording-cmdline.manifest
 @RESPATH@/components/htmlMenuBuilder.js
 @RESPATH@/components/htmlMenuBuilder.manifest
 
 @RESPATH@/components/PermissionSettings.js
--- a/browser/modules/ContentWebRTC.jsm
+++ b/browser/modules/ContentWebRTC.jsm
@@ -68,20 +68,20 @@ this.ContentWebRTC = {
         break;
       }
       case "webrtc:Allow": {
         let callID = aMessage.data.callID;
         let contentWindow = Services.wm.getOuterWindowWithId(aMessage.data.windowID);
         let devices = contentWindow.pendingGetUserMediaRequests.get(callID);
         forgetGUMRequest(contentWindow, callID);
 
-        let allowedDevices = Cc["@mozilla.org/supports-array;1"]
-                               .createInstance(Ci.nsISupportsArray);
+        let allowedDevices = Cc["@mozilla.org/array;1"]
+                               .createInstance(Ci.nsIMutableArray);
         for (let deviceIndex of aMessage.data.devices)
-           allowedDevices.AppendElement(devices[deviceIndex]);
+           allowedDevices.appendElement(devices[deviceIndex], /*weak =*/ false);
 
         Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", callID);
         break;
       }
       case "webrtc:Deny":
         denyGUMRequest(aMessage.data);
         break;
       case "webrtc:StopSharing":
@@ -256,18 +256,18 @@ function forgetPendingListsEventually(aC
     return;
   }
   aContentWindow.pendingGetUserMediaRequests = null;
   aContentWindow.pendingPeerConnectionRequests = null;
   aContentWindow.removeEventListener("unload", ContentWebRTC);
 }
 
 function updateIndicators() {
-  let contentWindowSupportsArray = MediaManagerService.activeMediaCaptureWindows;
-  let count = contentWindowSupportsArray.Count();
+  let contentWindowArray = MediaManagerService.activeMediaCaptureWindows;
+  let count = contentWindowArray.length;
 
   let state = {
     showGlobalIndicator: count > 0,
     showCameraIndicator: false,
     showMicrophoneIndicator: false,
     showScreenSharingIndicator: ""
   };
 
@@ -275,17 +275,17 @@ function updateIndicators() {
                .getService(Ci.nsIMessageSender);
   cpmm.sendAsyncMessage("webrtc:UpdatingIndicators");
 
   // If several iframes in the same page use media streams, it's possible to
   // have the same top level window several times. We use a Set to avoid
   // sending duplicate notifications.
   let contentWindows = new Set();
   for (let i = 0; i < count; ++i) {
-    contentWindows.add(contentWindowSupportsArray.GetElementAt(i).top);
+    contentWindows.add(contentWindowArray.queryElementAt(i, Ci.nsISupports).top);
   }
 
   for (let contentWindow of contentWindows) {
     let tabState = getTabStateForContentWindow(contentWindow);
     if (tabState.camera)
       state.showCameraIndicator = true;
     if (tabState.microphone)
       state.showMicrophoneIndicator = true;
--- a/browser/themes/linux/downloads/allDownloadsViewOverlay.css
+++ b/browser/themes/linux/downloads/allDownloadsViewOverlay.css
@@ -4,85 +4,8 @@
 
 %include ../../shared/downloads/allDownloadsViewOverlay.inc.css
 
 /*** List items ***/
 
 :root {
   --downloads-item-height: 5em;
 }
-
-/*** Button icons ***/
-
-.downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 16px, 16px, 0px);
-}
-@item@:hover .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 32px, 16px, 16px);
-}
-@item@:hover .downloadButton.downloadIconCancel:hover {
-  -moz-image-region: rect(0px, 48px, 16px, 32px);
-}
-@item@:hover .downloadButton.downloadIconCancel:active {
-  -moz-image-region: rect(0px, 64px, 16px, 48px);
-}
-@itemFocused@ .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 80px, 16px, 64px);
-}
-@itemFocused@:hover .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 96px, 16px, 80px);
-}
-@itemFocused@:hover .downloadButton.downloadIconCancel:hover {
-  -moz-image-region: rect(0px, 112px, 16px, 96px);
-}
-@itemFocused@:hover .downloadButton.downloadIconCancel:active {
-  -moz-image-region: rect(0px, 128px, 16px, 112px);
-}
-
-.downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 16px, 32px, 0px);
-}
-@item@:hover .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 32px, 32px, 16px);
-}
-@item@:hover .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 48px, 32px, 32px);
-}
-@item@:hover .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 64px, 32px, 48px);
-}
-@itemFocused@ .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 80px, 32px, 64px);
-}
-@itemFocused@:hover .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 96px, 32px, 80px);
-}
-@itemFocused@:hover .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 112px, 32px, 96px);
-}
-@itemFocused@:hover .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 128px, 32px, 112px);
-}
-
-.downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 16px, 48px, 0px);
-}
-@item@:hover .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 32px, 48px, 16px);
-}
-@item@:hover .downloadButton.downloadIconRetry:hover {
-  -moz-image-region: rect(32px, 48px, 48px, 32px);
-}
-@item@:hover .downloadButton.downloadIconRetry:active {
-  -moz-image-region: rect(32px, 64px, 48px, 48px);
-}
-@itemFocused@ .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 80px, 48px, 64px);
-}
-@itemFocused@:hover .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 96px, 48px, 80px);
-}
-@itemFocused@:hover .downloadButton.downloadIconRetry:hover {
-  -moz-image-region: rect(32px, 112px, 48px, 96px);
-}
-@itemFocused@:hover .downloadButton.downloadIconRetry:active {
-  -moz-image-region: rect(32px, 128px, 48px, 112px);
-}
deleted file mode 100644
index 0c91695aa5c5351fec6011df01bb2c364f28f749..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/linux/downloads/downloads.css
+++ b/browser/themes/linux/downloads/downloads.css
@@ -11,119 +11,24 @@
   outline: 1px -moz-dialogtext dotted;
   outline-offset: -5px;
 }
 
 /*** List items and similar elements in the summary ***/
 
 :root {
   --downloads-item-height: 6em;
-  --downloads-item-border-top-color: hsla(0,0%,100%,.2);
-  --downloads-item-border-bottom-color: hsla(0,0%,0%,.15);
   --downloads-item-font-size-factor: 0.9;
   --downloads-item-target-margin-bottom: 7px;
   --downloads-item-details-margin-top: 1px;
   --downloads-item-details-opacity: 0.6;
 }
 
 .downloadButton:focus > .button-box {
   outline: 1px -moz-dialogtext dotted;
 }
 
 /*** Highlighted list items ***/
 
 @keyfocus@ @itemFocused@ {
   outline: 1px -moz-dialogtext dotted;
   outline-offset: -1px;
 }
-
-@notKeyfocus@ @itemFinished@[exists]:hover,
-@item@[showingsubview] {
-  border-radius: 3px;
-  border-top: 1px solid hsla(0,0%,100%,.3);
-  border-bottom: 1px solid hsla(0,0%,0%,.2);
-  background-color: Highlight;
-  background-image: linear-gradient(hsla(0,0%,100%,.1), transparent);
-  color: HighlightText;
-  cursor: pointer;
-}
-
-@notKeyfocus@ @itemFinished@[exists][verdict="Malware"]:hover,
-@item@[showingsubview][verdict="Malware"] {
-  background-color: hsl(4, 82%, 47%);
-  color: white;
-}
-
-/*** Button icons ***/
-
-.downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 16px, 16px, 0px);
-}
-@item@:hover .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 32px, 16px, 16px);
-}
-@item@:hover .downloadButton.downloadIconCancel:hover {
-  -moz-image-region: rect(0px, 48px, 16px, 32px);
-}
-@item@:hover .downloadButton.downloadIconCancel:active {
-  -moz-image-region: rect(0px, 64px, 16px, 48px);
-}
-
-.downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 16px, 32px, 0px);
-}
-@itemNotFinished@:hover .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 32px, 32px, 16px);
-}
-@itemNotFinished@:hover .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 48px, 32px, 32px);
-}
-@itemNotFinished@:hover .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 64px, 32px, 48px);
-}
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 96px, 32px, 80px);
-}
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 112px, 32px, 96px);
-}
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 128px, 32px, 112px);
-}
-
-.downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 16px, 48px, 0px);
-}
-@item@:hover .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 32px, 48px, 16px);
-}
-@item@:hover .downloadButton.downloadIconRetry:hover {
-  -moz-image-region: rect(32px, 48px, 48px, 32px);
-}
-@item@:hover .downloadButton.downloadIconRetry:active {
-  -moz-image-region: rect(32px, 64px, 48px, 48px);
-}
-
-.downloadButton.downloadShowBlockedInfo {
-  -moz-image-region: rect(48px, 16px, 64px, 0px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo {
-  -moz-image-region: rect(48px, 32px, 64px, 16px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:hover {
-  -moz-image-region: rect(48px, 48px, 64px, 32px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:active {
-  -moz-image-region: rect(48px, 64px, 64px, 48px);
-}
-
-.downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 16px, 80px, 0px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 32px, 80px, 16px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:hover:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 48px, 80px, 32px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:active:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 64px, 80px, 48px);
-}
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -43,17 +43,16 @@ browser.jar:
   skin/classic/browser/webRTC-indicator.css
 * skin/classic/browser/controlcenter/panel.css        (controlcenter/panel.css)
   skin/classic/browser/customizableui/background-noise-toolbar.png  (customizableui/background-noise-toolbar.png)
   skin/classic/browser/customizableui/customizeMode-gridTexture.png  (customizableui/customizeMode-gridTexture.png)
   skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png  (customizableui/customizeMode-separatorHorizontal.png)
   skin/classic/browser/customizableui/customizeMode-separatorVertical.png  (customizableui/customizeMode-separatorVertical.png)
 * skin/classic/browser/customizableui/panelUI.css (customizableui/panelUI.css)
 * skin/classic/browser/downloads/allDownloadsViewOverlay.css   (downloads/allDownloadsViewOverlay.css)
-  skin/classic/browser/downloads/buttons.png          (downloads/buttons.png)
   skin/classic/browser/downloads/download-glow-menuPanel.png (downloads/download-glow-menuPanel.png)
   skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
   skin/classic/browser/downloads/download-notification-start.png (downloads/download-notification-start.png)
 * skin/classic/browser/downloads/downloads.css        (downloads/downloads.css)
   skin/classic/browser/feeds/feedIcon.png             (feeds/feedIcon.png)
   skin/classic/browser/feeds/feedIcon16.png           (feeds/feedIcon16.png)
   skin/classic/browser/feeds/subscribe.css            (feeds/subscribe.css)
   skin/classic/browser/feeds/subscribe-ui.css         (feeds/subscribe-ui.css)
--- a/browser/themes/osx/downloads/allDownloadsViewOverlay.css
+++ b/browser/themes/osx/downloads/allDownloadsViewOverlay.css
@@ -4,170 +4,8 @@
 
 %include ../../shared/downloads/allDownloadsViewOverlay.inc.css
 
 /*** List items ***/
 
 :root {
   --downloads-item-height: 6em;
 }
-
-/*** Button icons ***/
-
-.downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 16px, 16px, 0px);
-}
-@item@:hover .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 32px, 16px, 16px);
-}
-@item@:hover .downloadButton.downloadIconCancel:hover {
-  -moz-image-region: rect(0px, 48px, 16px, 32px);
-}
-@item@:hover .downloadButton.downloadIconCancel:active {
-  -moz-image-region: rect(0px, 64px, 16px, 48px);
-}
-@itemFocused@ .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 80px, 16px, 64px);
-}
-@itemFocused@:hover .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 96px, 16px, 80px);
-}
-@itemFocused@:hover .downloadButton.downloadIconCancel:hover {
-  -moz-image-region: rect(0px, 112px, 16px, 96px);
-}
-@itemFocused@:hover .downloadButton.downloadIconCancel:active {
-  -moz-image-region: rect(0px, 128px, 16px, 112px);
-}
-
-.downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 16px, 32px, 0px);
-}
-@item@:hover .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 32px, 32px, 16px);
-}
-@item@:hover .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 48px, 32px, 32px);
-}
-@item@:hover .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 64px, 32px, 48px);
-}
-@itemFocused@ .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 80px, 32px, 64px);
-}
-@itemFocused@:hover .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 96px, 32px, 80px);
-}
-@itemFocused@:hover .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 112px, 32px, 96px);
-}
-@itemFocused@:hover .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 128px, 32px, 112px);
-}
-
-.downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 16px, 48px, 0px);
-}
-@item@:hover .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 32px, 48px, 16px);
-}
-@item@:hover .downloadButton.downloadIconRetry:hover {
-  -moz-image-region: rect(32px, 48px, 48px, 32px);
-}
-@item@:hover .downloadButton.downloadIconRetry:active {
-  -moz-image-region: rect(32px, 64px, 48px, 48px);
-}
-@itemFocused@ .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 80px, 48px, 64px);
-}
-@itemFocused@:hover .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 96px, 48px, 80px);
-}
-@itemFocused@:hover .downloadButton.downloadIconRetry:hover {
-  -moz-image-region: rect(32px, 112px, 48px, 96px);
-}
-@itemFocused@:hover .downloadButton.downloadIconRetry:active {
-  -moz-image-region: rect(32px, 128px, 48px, 112px);
-}
-
-@media (min-resolution: 2dppx) {
-  .downloadButton {
-    list-style-image: url("chrome://browser/skin/downloads/buttons@2x.png");
-  }
-  .downloadButton > .button-box > .button-icon {
-    width: 16px;
-    height: 16px;
-  }
-
-  .downloadButton.downloadIconCancel {
-     -moz-image-region: rect(0px, 32px, 32px, 0px);
-  }
-  @item@:hover .downloadButton.downloadIconCancel {
-    -moz-image-region: rect(0px, 64px, 32px, 32px);
-  }
-  @item@:hover .downloadButton.downloadIconCancel:hover {
-    -moz-image-region: rect(0px, 96px, 32px, 64px);
-  }
-  @item@:hover .downloadButton.downloadIconCancel:active {
-    -moz-image-region: rect(0px, 128px, 32px, 96px);
-  }
-  @itemFocused@ .downloadButton.downloadIconCancel {
-    -moz-image-region: rect(0px, 160px, 32px, 128px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconCancel {
-    -moz-image-region: rect(0px, 192px, 32px, 160px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconCancel:hover {
-    -moz-image-region: rect(0px, 224px, 32px, 192px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconCancel:active {
-    -moz-image-region: rect(0px, 256px, 32px, 224px);
-  }
-
-  .downloadButton.downloadIconShow {
-    -moz-image-region: rect(32px, 32px, 64px, 0px);
-  }
-  @item@:hover .downloadButton.downloadIconShow {
-    -moz-image-region: rect(32px, 64px, 64px, 32px);
-  }
-  @item@:hover .downloadButton.downloadIconShow:hover {
-    -moz-image-region: rect(32px, 96px, 64px, 64px);
-  }
-  @item@:hover .downloadButton.downloadIconShow:active {
-    -moz-image-region: rect(32px, 128px, 64px, 96px);
-  }
-  @itemFocused@ .downloadButton.downloadIconShow {
-    -moz-image-region: rect(32px, 160px, 64px, 128px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconShow {
-    -moz-image-region: rect(32px, 192px, 64px, 160px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconShow:hover {
-    -moz-image-region: rect(32px, 224px, 64px, 192px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconShow:active {
-    -moz-image-region: rect(32px, 256px, 64px, 224px);
-  }
-
-  .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(64px, 32px, 96px, 0px);
-  }
-  @item@:hover .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(64px, 64px, 96px, 32px);
-  }
-  @item@:hover .downloadButton.downloadIconRetry:hover {
-    -moz-image-region: rect(64px, 96px, 96px, 64px);
-  }
-  @item@:hover .downloadButton.downloadIconRetry:active {
-    -moz-image-region: rect(64px, 128px, 96px, 96px);
-  }
-  @itemFocused@ .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(64px, 160px, 96px, 128px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(64px, 192px, 96px, 160px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconRetry:hover {
-    -moz-image-region: rect(64px, 224px, 96px, 192px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconRetry:active {
-    -moz-image-region: rect(64px, 256px, 96px, 224px);
-  }
-}
deleted file mode 100644
index 2aad9c7be2a2a56a9690ab1ea26a5a788399a807..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index fba4edbb53abee13b57c2a6b7e39329c5c19ed15..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/osx/downloads/downloads.css
+++ b/browser/themes/osx/downloads/downloads.css
@@ -15,329 +15,29 @@
   outline: 2px -moz-mac-focusring solid;
   outline-offset: -2px;
 }
 
 /*** List items and similar elements in the summary ***/
 
 :root {
   --downloads-item-height: 7em;
-  --downloads-item-border-top-color: hsla(0,0%,100%,.07);
-  --downloads-item-border-bottom-color: hsla(0,0%,0%,.2);
   --downloads-item-font-size-factor: 0.95;
   --downloads-item-target-margin-bottom: 6px;
   --downloads-item-details-margin-top: 0;
   --downloads-item-details-opacity: 0.7;
 }
 
 .downloadButton:focus > .button-box {
   outline: 2px -moz-mac-focusring solid;
   outline-offset: -2px;
 }
 
-/*** Highlighted list items ***/
-
-@keyfocus@ @itemFocused@,
-@notKeyfocus@ @itemFinished@[exists]:hover,
-@item@[showingsubview] {
-  border-radius: 3px;
-  border-top: 1px solid hsla(0,0%,100%,.2);
-  border-bottom: 1px solid hsla(0,0%,0%,.4);
-  background-color: Highlight;
-  color: HighlightText;
-}
-
-@item@[showingsubview] {
-  transition: background-color var(--panelui-subview-transition-duration),
-              color var(--panelui-subview-transition-duration);
-}
-
-@keyfocus@ @itemFocused@[verdict="Malware"],
-@notKeyfocus@ @itemFinished@[exists][verdict="Malware"]:hover,
-@item@[showingsubview][verdict="Malware"] {
-  background-color: hsl(4, 82%, 47%);
-  color: white;
-}
-
-@notKeyfocus@ @itemFinished@[exists]:hover {
-  cursor: pointer;
-}
-
-/*** Button icons ***/
-
-.downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 16px, 16px, 0px);
-}
-@item@:hover .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 32px, 16px, 16px);
-}
-@item@:hover .downloadButton.downloadIconCancel:hover {
-  -moz-image-region: rect(0px, 48px, 16px, 32px);
-}
-@item@:hover .downloadButton.downloadIconCancel:active {
-  -moz-image-region: rect(0px, 64px, 16px, 48px);
-}
-@keyfocus@ @itemFocused@ .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 80px, 16px, 64px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 96px, 16px, 80px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel:hover {
-  -moz-image-region: rect(0px, 112px, 16px, 96px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel:active {
-  -moz-image-region: rect(0px, 128px, 16px, 112px);
-}
-
-.downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 16px, 32px, 0px);
-}
-@notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow,
-@keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 32px, 32px, 16px);
-}
-@notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow:hover,
-@keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 48px, 32px, 32px);
-}
-@notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow:active,
-@keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 64px, 32px, 48px);
-}
-@keyfocus@ @itemFocused@ .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 80px, 32px, 64px);
-}
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow,
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 96px, 32px, 80px);
-}
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover,
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 112px, 32px, 96px);
-}
-@notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active,
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 128px, 32px, 112px);
-}
-
-.downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 16px, 48px, 0px);
-}
-@item@:hover .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 32px, 48px, 16px);
-}
-@item@:hover .downloadButton.downloadIconRetry:hover {
-  -moz-image-region: rect(32px, 48px, 48px, 32px);
-}
-@item@:hover .downloadButton.downloadIconRetry:active {
-  -moz-image-region: rect(32px, 64px, 48px, 48px);
-}
-@keyfocus@ @itemFocused@ .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 80px, 48px, 64px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 96px, 48px, 80px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry:hover {
-  -moz-image-region: rect(32px, 112px, 48px, 96px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry:active {
-  -moz-image-region: rect(32px, 128px, 48px, 112px);
-}
-
-.downloadButton.downloadShowBlockedInfo {
-  -moz-image-region: rect(48px, 16px, 64px, 0px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo {
-  -moz-image-region: rect(48px, 32px, 64px, 16px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:hover {
-  -moz-image-region: rect(48px, 48px, 64px, 32px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:active {
-  -moz-image-region: rect(48px, 64px, 64px, 48px);
-}
-@keyfocus@ @itemFocused@ .downloadButton.downloadShowBlockedInfo {
-  -moz-image-region: rect(48px, 80px, 64px, 64px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo {
-  -moz-image-region: rect(48px, 96px, 64px, 80px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:hover {
-  -moz-image-region: rect(48px, 112px, 64px, 96px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:active {
-  -moz-image-region: rect(48px, 128px, 64px, 112px);
+@item@[verdict="Malware"] {
+  color: #aa1b08;
 }
 
-.downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 16px, 80px, 0px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 32px, 80px, 16px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:hover:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 48px, 80px, 32px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:active:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 64px, 80px, 48px);
-}
-@keyfocus@ @itemFocused@ .downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 80px, 80px, 64px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 96px, 80px, 80px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:hover:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 112px, 80px, 96px);
-}
-@keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:active:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 128px, 80px, 112px);
-}
-
-@media (min-resolution: 2dppx) {
-  .downloadButton {
-    list-style-image: url("chrome://browser/skin/downloads/buttons@2x.png");
-  }
-  .downloadButton > .button-box > .button-icon {
-    width: 16px;
-    height: 16px;
-  }
-
-  .downloadButton.downloadIconCancel {
-    -moz-image-region: rect(0px, 32px, 32px, 0px);
-  }
-  @item@:hover .downloadButton.downloadIconCancel {
-    -moz-image-region: rect(0px, 64px, 32px, 32px);
-  }
-  @item@:hover .downloadButton.downloadIconCancel:hover {
-    -moz-image-region: rect(0px, 96px, 32px, 64px);
-  }
-  @item@:hover .downloadButton.downloadIconCancel:active {
-    -moz-image-region: rect(0px, 128px, 32px, 96px);
-  }
-  @keyfocus@ @itemFocused@ .downloadButton.downloadIconCancel {
-    -moz-image-region: rect(0px, 160px, 32px, 128px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel {
-    -moz-image-region: rect(0px, 192px, 32px, 160px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel:hover {
-    -moz-image-region: rect(0px, 224px, 32px, 192px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconCancel:active {
-    -moz-image-region: rect(0px, 256px, 32px, 224px);
-  }
+/*** Highlighted list items ***/
 
-  .downloadButton.downloadIconShow {
-    -moz-image-region: rect(32px, 32px, 64px, 0px);
-  }
-  @notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow,
-  @keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow {
-    -moz-image-region: rect(32px, 64px, 64px, 32px);
-  }
-  @notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow:hover,
-  @keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow:hover {
-    -moz-image-region: rect(32px, 96px, 64px, 64px);
-  }
-  @notKeyfocus@ @itemNotFinished@:hover .downloadButton.downloadIconShow:active,
-  @keyfocus@ @itemFinished@:hover:not([selected]) .downloadButton.downloadIconShow:active {
-    -moz-image-region: rect(32px, 128px, 64px, 96px);
-  }
-  @keyfocus@ @itemFocused@ .downloadButton.downloadIconShow {
-    -moz-image-region: rect(32px, 160px, 64px, 128px);
-  }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow,
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow {
-    -moz-image-region: rect(32px, 192px, 64px, 160px);
-  }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover,
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow:hover {
-    -moz-image-region: rect(32px, 224px, 64px, 192px);
-  }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active,
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconShow:active {
-    -moz-image-region: rect(32px, 256px, 64px, 224px);
-  }
-
-  .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(64px, 32px, 96px, 0px);
-  }
-  @item@:hover .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(64px, 64px, 96px, 32px);
-  }
-  @item@:hover .downloadButton.downloadIconRetry:hover {
-    -moz-image-region: rect(64px, 96px, 96px, 64px);
-  }
-  @item@:hover .downloadButton.downloadIconRetry:active {
-    -moz-image-region: rect(64px, 128px, 96px, 96px);
-  }
-  @keyfocus@ @itemFocused@ .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(64px, 160px, 96px, 128px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(64px, 192px, 96px, 160px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry:hover {
-    -moz-image-region: rect(64px, 224px, 96px, 192px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadIconRetry:active {
-    -moz-image-region: rect(64px, 256px, 96px, 224px);
-  }
-
-  .downloadButton.downloadShowBlockedInfo {
-    -moz-image-region: rect(96px, 32px, 128px, 0px);
-  }
-  @item@:hover .downloadButton.downloadShowBlockedInfo {
-    -moz-image-region: rect(96px, 64px, 128px, 32px);
-  }
-  @item@:hover .downloadButton.downloadShowBlockedInfo:hover {
-    -moz-image-region: rect(96px, 96px, 128px, 64px);
-  }
-  @item@:hover .downloadButton.downloadShowBlockedInfo:active {
-    -moz-image-region: rect(96px, 128px, 128px, 96px);
-  }
-  @keyfocus@ @itemFocused@ .downloadButton.downloadShowBlockedInfo {
-    -moz-image-region: rect(96px, 160px, 128px, 128px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo {
-    -moz-image-region: rect(96px, 192px, 128px, 160px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:hover {
-    -moz-image-region: rect(96px, 224px, 128px, 192px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:active {
-    -moz-image-region: rect(96px, 256px, 128px, 224px);
-  }
-
-  .downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-    -moz-image-region: rect(128px, 32px, 160px, 0px);
-  }
-  @item@:hover .downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-    -moz-image-region: rect(128px, 64px, 160px, 32px);
-  }
-  @item@:hover .downloadButton.downloadShowBlockedInfo:hover:-moz-locale-dir(rtl) {
-    -moz-image-region: rect(128px, 96px, 160px, 64px);
-  }
-  @item@:hover .downloadButton.downloadShowBlockedInfo:active:-moz-locale-dir(rtl) {
-    -moz-image-region: rect(128px, 128px, 160px, 96px);
-  }
-  @keyfocus@ @itemFocused@ .downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-    -moz-image-region: rect(128px, 160px, 160px, 128px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-    -moz-image-region: rect(128px, 192px, 160px, 160px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:hover:-moz-locale-dir(rtl) {
-    -moz-image-region: rect(128px, 224px, 160px, 192px);
-  }
-  @keyfocus@ @itemFocused@:hover .downloadButton.downloadShowBlockedInfo:active:-moz-locale-dir(rtl) {
-    -moz-image-region: rect(128px, 256px, 160px, 224px);
-  }
-
-  #downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="subview"] .download-state[showingsubview] .downloadButton {
-    list-style-image: url("chrome://browser/skin/customizableui/subView-arrow-back-inverted@2x.png");
-  }
-  #downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="subview"] .download-state[showingsubview] .downloadButton:-moz-locale-dir(rtl) {
-    list-style-image: url("chrome://browser/skin/customizableui/subView-arrow-back-inverted-rtl@2x.png");
-  }
+@keyfocus@ @itemFocused@ {
+  outline: 2px -moz-mac-focusring solid;
+  outline-offset: -2px;
 }
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -63,18 +63,16 @@ browser.jar:
   skin/classic/browser/customizableui/background-noise-toolbar.png  (customizableui/background-noise-toolbar.png)
   skin/classic/browser/customizableui/customize-titleBar-toggle.png  (customizableui/customize-titleBar-toggle.png)
   skin/classic/browser/customizableui/customize-titleBar-toggle@2x.png  (customizableui/customize-titleBar-toggle@2x.png)
   skin/classic/browser/customizableui/customizeMode-gridTexture.png  (customizableui/customizeMode-gridTexture.png)
   skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png  (customizableui/customizeMode-separatorHorizontal.png)
   skin/classic/browser/customizableui/customizeMode-separatorVertical.png  (customizableui/customizeMode-separatorVertical.png)
 * skin/classic/browser/customizableui/panelUI.css    (customizableui/panelUI.css)
 * skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
-  skin/classic/browser/downloads/buttons.png                (downloads/buttons.png)
-  skin/classic/browser/downloads/buttons@2x.png             (downloads/buttons@2x.png)
   skin/classic/browser/downloads/download-glow-menuPanel.png (downloads/download-glow-menuPanel.png)
   skin/classic/browser/downloads/download-glow-menuPanel@2x.png (downloads/download-glow-menuPanel@2x.png)
   skin/classic/browser/downloads/download-notification-finish.png  (downloads/download-notification-finish.png)
   skin/classic/browser/downloads/download-notification-finish@2x.png  (downloads/download-notification-finish@2x.png)
   skin/classic/browser/downloads/download-notification-start.png  (downloads/download-notification-start.png)
   skin/classic/browser/downloads/download-notification-start@2x.png  (downloads/download-notification-start@2x.png)
 * skin/classic/browser/downloads/downloads.css              (downloads/downloads.css)
   skin/classic/browser/feeds/subscribe.css                  (feeds/subscribe.css)
--- a/browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css
+++ b/browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css
@@ -60,29 +60,94 @@
 @item@[verdict="PotentiallyUnwanted"] .downloadBlockedBadge {
   background-image: url("chrome://browser/skin/warning.svg");
 }
 
 @item@[verdict="Uncommon"] .downloadBlockedBadge {
   background-image: url("chrome://browser/skin/info.svg");
 }
 
+@item@ > toolbarseparator {
+  display: none;
+}
+
 .downloadTarget {
   margin-bottom: 3px;
   cursor: inherit;
 }
 
 .downloadDetails {
   opacity: 0.7;
   font-size: 95%;
   cursor: inherit;
 }
 
 .downloadButton {
   -moz-appearance: none;
+  -moz-box-align: center;
   background: transparent;
   min-width: 0;
   min-height: 0;
   margin: 3px;
   border: none;
   padding: 5px;
-  list-style-image: url("chrome://browser/skin/downloads/buttons.png");
+  color: inherit;
+}
+
+.downloadButton > .button-box {
+  -moz-appearance: none;
+  padding: 2px !important;
+  border-radius: 50%;
+  color: graytext;
+}
+
+.downloadButton > .button-box > .button-icon {
+  width: 16px;
+  height: 16px;
+  margin: 0;
+  filter: url("chrome://browser/skin/filters.svg#fill");
+  fill: currentColor;
+}
+
+.downloadButton > .button-box > .button-text {
+  display: none;
+}
+
+.downloadButton:hover > .button-box {
+  background-color: graytext;
+  color: -moz-field;
+}
+
+.downloadButton:hover:active > .button-box {
+  background-color: -moz-fieldtext;
 }
+
+@itemFocused@ > .downloadButtonArea > .downloadButton > .button-box {
+  color: inherit;
+}
+
+@itemFocused@ > .downloadButtonArea > .downloadButton:hover > .button-box {
+  background-color: HighlightText;
+  color: Highlight;
+}
+
+@itemFocused@ > .downloadButtonArea > .downloadButton:hover:active > .button-box {
+  background-color: -moz-field;
+  color: -moz-fieldtext;
+}
+
+/*** Button icons ***/
+
+.downloadIconCancel > .button-box > .button-icon {
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#cancel");
+}
+
+.downloadIconShow > .button-box > .button-icon {
+%ifdef XP_MACOSX
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#magnifier");
+%else
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#folder");
+%endif
+}
+
+.downloadIconRetry > .button-box > .button-icon {
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#retry");
+}
--- a/browser/themes/shared/downloads/downloads.inc.css
+++ b/browser/themes/shared/downloads/downloads.inc.css
@@ -20,17 +20,17 @@
 
 #downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent,
 #downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews {
   padding: 0;
 }
 
 #downloadsListBox {
   background: transparent;
-  padding: 4px;
+  padding: 0;
   color: inherit;
   -moz-appearance: none;
   margin: 0;
   border: none;
 }
 
 #emptyDownloads {
   padding: 16px 25px;
@@ -40,17 +40,18 @@
   text-align: center;
 }
 
 .downloadsPanelFooter {
   background-color: var(--arrowpanel-dimmed);
   border-top: 1px solid var(--panel-separator-color);
 }
 
-.downloadsPanelFooter toolbarseparator {
+.downloadsPanelFooter toolbarseparator,
+@item@ > toolbarseparator {
   margin: 0;
   border: 0;
   min-width: 0;
   border-left: 1px solid var(--panel-separator-color);
   -moz-appearance: none;
 }
 
 .downloadsPanelFooterButton {
@@ -103,16 +104,21 @@
 #downloadsPanel[hasdownloads] #downloadsFooterButtons:not(.downloadsHideDropmarker) > #downloadsHistory {
   padding-inline-start: 68px;
 }
 
 toolbarseparator.downloadsDropmarkerSplitter {
   margin: 7px 0;
 }
 
+@item@ > toolbarseparator {
+  margin: 10px 0;
+}
+
+@item@:hover > toolbarseparator,
 #downloadsFooter:hover toolbarseparator.downloadsDropmarkerSplitter,
 #downloadsFooter[showingdropdown] toolbarseparator {
   margin: 0;
 }
 
 .downloadsDropmarker {
   padding: 0 21px;
 }
@@ -163,28 +169,27 @@ toolbarseparator.downloadsDropmarkerSpli
 richlistitem[type="download"] {
   height: var(--downloads-item-height);
   padding-inline-end: 0;
   color: inherit;
 }
 
 richlistitem[type="download"] {
   margin: 0;
-  border-top: 1px solid var(--downloads-item-border-top-color);
-  border-bottom: 1px solid var(--downloads-item-border-bottom-color);
+  border-bottom: 1px solid var(--panel-separator-color);
   background: transparent;
-  padding: 8px;
-}
-
-richlistitem[type="download"]:first-child {
-  border-top: 1px solid transparent;
+  padding: 0;
 }
 
 richlistitem[type="download"]:last-child {
-  border-bottom: 1px solid transparent;
+  border-bottom: none;
+}
+
+richlistitem[type="download"] > .downloadMainArea {
+  padding: 8px;
 }
 
 .downloadTypeIcon {
   margin-top: 8px;
   margin-inline-end: 12px;
   margin-bottom: 8px;
   margin-inline-start: 0;
   width: 32px;
@@ -239,48 +244,124 @@ richlistitem[type="download"]:last-child
 
 #downloadsSummaryDetails,
 .downloadDetails {
   margin-top: var(--downloads-item-details-margin-top);
   opacity: var(--downloads-item-details-opacity);
   cursor: inherit;
 }
 
+@item@[verdict] > toolbarseparator {
+  visibility: hidden;
+}
+
 .downloadButton {
   -moz-appearance: none;
-  min-width: 0;
-  min-height: 0;
-  margin: 3px;
+  min-width: 58px;
+  margin: 0;
   border: none;
   background: transparent;
-  padding: 5px;
-  list-style-image: url("chrome://browser/skin/downloads/buttons.png");
+  padding: 8px;
+  color: graytext;
 }
 
-.downloadButton > .button-box {
+.downloadButton > .button-box > .button-icon {
+  width: 16px;
+  height: 16px;
+  margin: 1px;
+  filter: url("chrome://browser/skin/filters.svg#fill");
+  fill: currentColor;
+}
+
+.downloadButton > .button-box > .button-text {
+  margin: 0 !important;
   padding: 0;
 }
 
+@itemFinished@[exists]:hover > .downloadMainArea,
+@item@:not([verdict]):hover > .downloadButtonArea {
+  background-color: var(--arrowpanel-dimmed);
+}
+
+@itemFinished@[exists] .downloadMainArea:hover,
+@item@:not([verdict]) > .downloadButtonArea:hover,
+@item@[verdict]:hover {
+  background-color: var(--arrowpanel-dimmed-further);
+}
+
+@itemFinished@[exists] > .downloadMainArea:hover:active,
+@item@:not([verdict]) > .downloadButtonArea:hover:active,
+@item@[verdict]:hover:active {
+  background-color: var(--arrowpanel-dimmed-even-further);
+}
+
+@item@[showingsubview] {
+  background-color: Highlight;
+  color: HighlightText;
+  transition: background-color var(--panelui-subview-transition-duration),
+              color var(--panelui-subview-transition-duration);
+}
+
+@item@[verdict="Malware"]:hover,
+@item@[verdict="Malware"]:hover:active,
+@item@[verdict="Malware"][showingsubview] {
+  background-color: #aa1b08;
+  color: white;
+}
+
+@item@[verdict="Malware"]:hover > .downloadButtonArea > .downloadButton {
+  color: inherit;
+}
+
+/*** Button icons ***/
+
+.downloadIconCancel > .button-box > .button-icon {
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#cancel");
+}
+
+.downloadIconShow > .button-box > .button-icon {
+%ifdef XP_MACOSX
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#magnifier");
+%else
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#folder");
+%endif
+}
+
+.downloadIconRetry > .button-box > .button-icon {
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#retry");
+}
+
+.downloadShowBlockedInfo > .button-box > .button-icon {
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#arrow-right");
+}
+
+.downloadShowBlockedInfo > .button-box > .button-icon:-moz-locale-dir(rtl) {
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#arrow-left");
+}
 
 /*** Blocked subview ***/
 
 #downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype=main] > .panel-subviews {
   /* When the main view is showing, the shadow on the left edge of the subview is
      barely visible on the right edge of the main view, so set it to none. */
   box-shadow: none;
 }
 
 /* When the subview is showing, turn the download button into an arrow pointing
    back to the main view. */
 #downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="subview"] .download-state[showingsubview] .downloadButton {
-  list-style-image: url("chrome://browser/skin/customizableui/subView-arrow-back-inverted.png");
+  color: HighlightText;
 }
 
-#downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="subview"] .download-state[showingsubview] .downloadButton:-moz-locale-dir(rtl) {
-  list-style-image: url("chrome://browser/skin/customizableui/subView-arrow-back-inverted-rtl.png");
+#downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="subview"] .download-state[showingsubview] .downloadButton > .button-box > .button-icon {
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#arrow-left");
+}
+
+#downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="subview"] .download-state[showingsubview] .downloadButton > .button-box > .button-icon:-moz-locale-dir(rtl) {
+  list-style-image: url("chrome://browser/skin/panel-icons.svg#arrow-right");
 }
 
 #downloadsPanel-blockedSubview {
   background-image: url("chrome://browser/skin/warning.svg");
   background-size: 32px 32px;
   background-position: 16px 16px;
   background-repeat: no-repeat;
 }
--- a/browser/themes/shared/panel-icons.svg
+++ b/browser/themes/shared/panel-icons.svg
@@ -1,8 +1,18 @@
 <?xml version="1.0"?>
 <!-- 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"
      width="32" height="32" viewBox="0 0 32 32">
+  <style>
+    path:not(:target) {
+      display: none;
+    }
+  </style>
   <path id="cancel" d="m 6,9.5 6.5,6.5 -6.5,6.5 3.5,3.5 6.5,-6.5 6.5,6.5 3.5,-3.5 -6.5,-6.5 6.5,-6.5 -3.5,-3.5 -6.5,6.5 -6.5,-6.5 z" />
+  <path id="folder" d="M17.3,9.4c0,0,1.1,0,3.7,0c1.7,0,2,0,5.6,0c0.6,0,0.6,0,1.1,0V9.2c0-1.5-0.9-2.6-2-2.6h-5.8V6.3c0-0.6-1.5-2-2.8-2h-7.1 H7.6H4.9v2.4v2.4v2.2c2.8,0,8.5,0,8.5,0C16.4,11.3,17.3,9.4,17.3,9.4z M29,13c0-0.6-0.6-1.1-1.5-1.7l0,0c-0.2,0-0.6,0-0.9,0 c-2.8,0-3,0-4.8,0c-1.9,0-3.3,0-3.3,0s-1.5,2.4-3.7,2.4c0,0-6.5,0-9.1,0H5.4C3,13.7,3,15.9,3,15.9l1.1,9.7C4.1,27.1,5,28,6.5,28 h19.1c1.5,0,2.4-0.9,2.4-2.4L29,13.7l0,0l0,0C29,13.7,29,13,29,13z" />
+  <path id="magnifier" d="M12.9,2c6,0,11,5,11,11c0,2.2-0.6,4.2-1.8,6l7.2,7c0.8,0.8,0.8,2.4,0,3.2c-0.6,0.6-1.2,0.8-1.6,0.8s-1.2-0.2-1.6-0.6l-7-7 c-1.8,1.2-3.8,1.8-6,1.8c-6,0-11-5-11-11C2.1,7.2,6.9,2,12.9,2z M12.9,20c3.8,0,7-3.2,7-7s-3.2-7-7-7s-7,3.2-7,7S9.1,20,12.9,20z" />
+  <path id="retry" d="M28,16.5v-14l-5,4.8c-1.8-1.4-4.4-2.4-7-2.4c-6.4,0-11.8,5.2-11.8,11.8c0,6.4,5.2,11.8,11.8,11.8c3.4,0,6.2-1.4,8.2-3.6 l-3.4-3.4c-1.2,1.2-3,1.8-5,1.8c-3.6,0.2-6.8-2.8-6.8-6.8c0-3.8,3-7.2,7-7.2c1.4,0,2.6,0.4,3.6,1l-6,6.2H28z"/>
+  <path id="arrow-left" d="M23.5,25l-9-9l9-9l-3-3l-12,12l12,12L23.5,25z" />
+  <path id="arrow-right" d="M11.6,28l12-12l-12-12l-3,3l9,9l-9,9L11.6,28z" />
 </svg>
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2642,8 +2642,62 @@ notification.pluginVulnerable > .notific
   .cui-widget-panelview[id^=PanelUI-webext-] {
     border-radius: 4px;
   }
 }
 
 .webextension-popup-browser {
   border-radius: inherit;
 }
+
+.contentSelectDropdown-ingroup > .menu-iconic-text {
+  padding-inline-start: 20px;
+}
+
+#ContentSelectDropdown > menupopup {
+  background-color: -moz-field;
+  -moz-border-top-colors: GrayText;
+  -moz-border-right-colors: GrayText;
+  -moz-border-bottom-colors: GrayText;
+  -moz-border-left-colors: GrayText;
+}
+
+#ContentSelectDropdown > menupopup > menucaption,
+#ContentSelectDropdown > menupopup > menuitem {
+  padding: 4px 6px;
+}
+
+#ContentSelectDropdown > menupopup > menucaption > .menu-iconic-text,
+#ContentSelectDropdown > menupopup > menuitem > .menu-iconic-text {
+  font: message-box;
+  font-size: 11px;
+  /**
+   * Remove the extra vertical padding set by menu.css since
+   * the menuitem itself will include enough padding.
+   */
+  padding-top: 0px;
+  padding-bottom: 0px;
+}
+
+#ContentSelectDropdown > menupopup > menucaption > .menu-iconic-text {
+  font-weight: bold;
+}
+
+#ContentSelectDropdown > menupopup > menuitem[_moz-menuactive="true"][disabled="true"] {
+  color: GrayText;
+  background-color: unset;
+}
+
+#ContentSelectDropdown > menupopup > menucaption {
+  background-color: buttonface;
+}
+
+#ContentSelectDropdown > menupopup > menucaption[disabled="true"] {
+  color: GrayText;
+}
+
+@media (-moz-touch-enabled) {
+  #ContentSelectDropdown > menupopup > menucaption,
+  #ContentSelectDropdown > menupopup > menuitem {
+    padding-top: 11px;
+    padding-bottom: 11px;
+  }
+}
--- a/browser/themes/windows/downloads/allDownloadsViewOverlay.css
+++ b/browser/themes/windows/downloads/allDownloadsViewOverlay.css
@@ -36,90 +36,8 @@
       background-clip: content-box;
       border-radius: 6px;
       outline: 1px solid rgb(124,163,206);
       -moz-outline-radius: 3px;
       outline-offset: -2px;
     }
   }
 }
-
-/*** Button icons ***/
-
-.downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 16px, 16px, 0px);
-}
-@item@:hover .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 32px, 16px, 16px);
-}
-@item@:hover .downloadButton.downloadIconCancel:hover {
-  -moz-image-region: rect(0px, 48px, 16px, 32px);
-}
-@item@:hover .downloadButton.downloadIconCancel:active {
-  -moz-image-region: rect(0px, 64px, 16px, 48px);
-}
-
-.downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 16px, 32px, 0px);
-}
-@item@:hover .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 32px, 32px, 16px);
-}
-@item@:hover .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 48px, 32px, 32px);
-}
-@item@:hover .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 64px, 32px, 48px);
-}
-
-.downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 16px, 48px, 0px);
-}
-@item@:hover .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 32px, 48px, 16px);
-}
-@item@:hover .downloadButton.downloadIconRetry:hover {
-  -moz-image-region: rect(32px, 48px, 48px, 32px);
-}
-@item@:hover .downloadButton.downloadIconRetry:active {
-  -moz-image-region: rect(32px, 64px, 48px, 48px);
-}
-
-@media (-moz-os-version: windows-xp) {
-  @itemFocused@ .downloadButton.downloadIconCancel {
-    -moz-image-region: rect(0px, 80px, 16px, 64px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconCancel {
-    -moz-image-region: rect(0px, 96px, 16px, 80px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconCancel:hover {
-    -moz-image-region: rect(0px, 112px, 16px, 96px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconCancel:active {
-    -moz-image-region: rect(0px, 128px, 16px, 112px);
-  }
-
-  @itemFocused@ .downloadButton.downloadIconShow {
-    -moz-image-region: rect(16px, 80px, 32px, 64px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconShow {
-    -moz-image-region: rect(16px, 96px, 32px, 80px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconShow:hover {
-    -moz-image-region: rect(16px, 112px, 32px, 96px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconShow:active {
-    -moz-image-region: rect(16px, 128px, 32px, 112px);
-  }
-
-  @itemFocused@ .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(32px, 80px, 48px, 64px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconRetry {
-    -moz-image-region: rect(32px, 96px, 48px, 80px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconRetry:hover {
-    -moz-image-region: rect(32px, 112px, 48px, 96px);
-  }
-  @itemFocused@:hover .downloadButton.downloadIconRetry:active {
-    -moz-image-region: rect(32px, 128px, 48px, 112px);
-  }
-}
deleted file mode 100644
index b8a97d3750ab5220f53134acab45f6fb6c88c911..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 9611a8f8ca8e3c13cff5d2b92137f8a9fc1a9faf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/windows/downloads/downloads.css
+++ b/browser/themes/windows/downloads/downloads.css
@@ -54,182 +54,34 @@
 @keyfocus@ #downloadsSummary:focus {
   outline-offset: -5px;
 }
 
 /*** List items and similar elements in the summary ***/
 
 :root {
   --downloads-item-height: 7em;
-  --downloads-item-border-top-color: hsla(0,0%,100%,.3);
-  --downloads-item-border-bottom-color: hsla(220,18%,51%,.25);
   --downloads-item-font-size-factor: 0.9;
   --downloads-item-target-margin-bottom: 6px;
   --downloads-item-details-margin-top: 0;
   --downloads-item-details-opacity: 0.6;
 }
 
-@media (-moz-windows-default-theme) and (-moz-os-version: windows-vista),
-       (-moz-windows-default-theme) and (-moz-os-version: windows-win7) {
-  richlistitem[type="download"] {
-    border: 1px solid transparent;
-    border-bottom: 1px solid hsl(213,40%,90%);
-  }
-}
-
 .downloadButton > .button-box {
   border: 1px solid transparent;
 }
 
 @keyfocus@ .downloadButton:focus > .button-box {
   border: 1px dotted ThreeDDarkShadow;
 }
 
+@media (-moz-windows-default-theme) {
+  @item@[verdict="Malware"] {
+    color: #aa1b08;
+  }
+}
+
 /*** Highlighted list items ***/
 
 @keyfocus@ @itemFocused@ {
   outline: 1px -moz-dialogtext dotted;
   outline-offset: -1px;
 }
-
-@notKeyfocus@ @itemFinished@[exists]:hover {
-  background-color: hsla(210,4%,10%,.08);
-  outline: 1px solid hsla(210,4%,10%,.1);
-  outline-offset: -1px;
-  cursor: pointer;
-}
-
-@notKeyfocus@ @itemFinished@[exists]:hover:active {
-  background-color: hsla(210,4%,10%,.15);
-  outline: 1px solid hsla(210,4%,10%,.15);
-  box-shadow: 0 1px 0 0 hsla(210,4%,10%,.05) inset;
-}
-
-@item@[showingsubview] {
-  background-color: Highlight;
-  color: HighlightText;
-  transition: background-color var(--panelui-subview-transition-duration),
-              color var(--panelui-subview-transition-duration);
-}
-
-@notKeyfocus@ @itemFinished@[exists][verdict="Malware"]:hover,
-@notKeyfocus@ @itemFinished@[exists][verdict="Malware"]:hover:active,
-@item@[showingsubview][verdict="Malware"] {
-  background-color: hsl(4, 82%, 47%);
-  color: white;
-}
-
-@media (-moz-os-version: windows-xp),
-       (-moz-os-version: windows-vista),
-       (-moz-os-version: windows-win7) {
-  @notKeyfocus@ @itemFinished@[exists]:hover {
-    border-radius: 3px;
-    outline: 0;
-    border-top: 1px solid hsla(0,0%,100%,.2);
-    border-bottom: 1px solid hsla(0,0%,0%,.2);
-    background-color: Highlight;
-    color: HighlightText;
-  }
-
-  @notKeyfocus@ @itemFinished@[exists]:hover:active {
-    background-color: Highlight;
-    outline: 0;
-    box-shadow: none;
-  }
-}
-
-@media (-moz-windows-default-theme) and (-moz-os-version: windows-vista),
-       (-moz-windows-default-theme) and (-moz-os-version: windows-win7) {
-  @notKeyfocus@ @itemFinished@[exists]:hover {
-    border: 1px solid hsl(213,45%,65%);
-    box-shadow: 0 0 0 1px hsla(0,0%,100%,.5) inset,
-                0 1px 0 hsla(0,0%,100%,.3) inset;
-    background-image: linear-gradient(hsl(212,86%,92%), hsl(212,91%,86%));
-    color: black;
-  }
-}
-
-/*** Button icons ***/
-
-.downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 16px, 16px, 0px);
-}
-@item@:hover .downloadButton.downloadIconCancel {
-  -moz-image-region: rect(0px, 32px, 16px, 16px);
-}
-@item@:hover .downloadButton.downloadIconCancel:hover {
-  -moz-image-region: rect(0px, 48px, 16px, 32px);
-}
-@item@:hover .downloadButton.downloadIconCancel:active {
-  -moz-image-region: rect(0px, 64px, 16px, 48px);
-}
-
-.downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 16px, 32px, 0px);
-}
-@item@:hover .downloadButton.downloadIconShow {
-  -moz-image-region: rect(16px, 32px, 32px, 16px);
-}
-@item@:hover .downloadButton.downloadIconShow:hover {
-  -moz-image-region: rect(16px, 48px, 32px, 32px);
-}
-@item@:hover .downloadButton.downloadIconShow:active {
-  -moz-image-region: rect(16px, 64px, 32px, 48px);
-}
-@media (-moz-os-version: windows-xp) {
-  @keyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow {
-    -moz-image-region: rect(16px, 32px, 32px, 16px);
-  }
-  @keyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover {
-    -moz-image-region: rect(16px, 48px, 32px, 32px);
-  }
-  @keyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active {
-    -moz-image-region: rect(16px, 64px, 32px, 48px);
-  }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow {
-    -moz-image-region: rect(16px, 96px, 32px, 80px);
-  }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:hover {
-    -moz-image-region: rect(16px, 112px, 32px, 96px);
-  }
-  @notKeyfocus@ @itemFinished@:hover .downloadButton.downloadIconShow:active {
-    -moz-image-region: rect(16px, 128px, 32px, 112px);
-  }
-}
-
-.downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 16px, 48px, 0px);
-}
-@item@:hover .downloadButton.downloadIconRetry {
-  -moz-image-region: rect(32px, 32px, 48px, 16px);
-}
-@item@:hover .downloadButton.downloadIconRetry:hover {
-  -moz-image-region: rect(32px, 48px, 48px, 32px);
-}
-@item@:hover .downloadButton.downloadIconRetry:active {
-  -moz-image-region: rect(32px, 64px, 48px, 48px);
-}
-
-.downloadButton.downloadShowBlockedInfo {
-  -moz-image-region: rect(48px, 16px, 64px, 0px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo {
-  -moz-image-region: rect(48px, 32px, 64px, 16px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:hover {
-  -moz-image-region: rect(48px, 48px, 64px, 32px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:active {
-  -moz-image-region: rect(48px, 64px, 64px, 48px);
-}
-
-.downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 16px, 80px, 0px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 32px, 80px, 16px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:hover:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 48px, 80px, 32px);
-}
-@item@:hover .downloadButton.downloadShowBlockedInfo:active:-moz-locale-dir(rtl) {
-  -moz-image-region: rect(64px, 64px, 80px, 48px);
-}
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -72,18 +72,16 @@ browser.jar:
   skin/classic/browser/customizableui/customize-titleBar-toggle.png  (customizableui/customize-titleBar-toggle.png)
   skin/classic/browser/customizableui/customize-titleBar-toggle@2x.png  (customizableui/customize-titleBar-toggle@2x.png)
   skin/classic/browser/customizableui/customizeMode-gridTexture.png  (customizableui/customizeMode-gridTexture.png)
   skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png  (customizableui/customizeMode-separatorHorizontal.png)
   skin/classic/browser/customizableui/customizeMode-separatorVertical.png  (customizableui/customizeMode-separatorVertical.png)
   skin/classic/browser/customizableui/menu-arrow.svg           (customizableui/menu-arrow.svg)
 * skin/classic/browser/customizableui/panelUI.css       (customizableui/panelUI.css)
 * skin/classic/browser/downloads/allDownloadsViewOverlay.css   (downloads/allDownloadsViewOverlay.css)
-  skin/classic/browser/downloads/buttons.png                   (downloads/buttons.png)
-  skin/classic/browser/downloads/buttons-XP.png                (downloads/buttons-XP.png)
   skin/classic/browser/downloads/download-glow-menuPanel.png   (downloads/download-glow-menuPanel.png)
   skin/classic/browser/downloads/download-glow-menuPanel-XPVista7.png   (downloads/download-glow-menuPanel-XPVista7.png)
   skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
   skin/classic/browser/downloads/download-notification-start.png (downloads/download-notification-start.png)
 * skin/classic/browser/downloads/downloads.css                 (downloads/downloads.css)
   skin/classic/browser/feeds/feedIcon.png                      (feeds/feedIcon.png)
   skin/classic/browser/feeds/feedIcon16.png                    (feeds/feedIcon16.png)
   skin/classic/browser/feeds/feedIcon-XP.png                   (feeds/feedIcon-XP.png)
@@ -209,17 +207,16 @@ browser.jar:
 % override chrome://browser/skin/aboutSessionRestore-window-icon.png  chrome://browser/skin/preferences/application.png                 os!=WINNT
 % override chrome://browser/skin/aboutSessionRestore-window-icon.png  chrome://browser/skin/preferences/application.png                 os=WINNT osversion<6
 
 % override chrome://browser/skin/Info.png                             chrome://browser/skin/Info-XP.png                                 os=WINNT osversion<6
 % override chrome://browser/skin/livemark-folder.png                  chrome://browser/skin/livemark-folder-XP.png                      os=WINNT osversion<6
 % override chrome://browser/skin/menu-back.png                        chrome://browser/skin/menu-back-XP.png                            os=WINNT osversion<6
 % override chrome://browser/skin/menu-forward.png                     chrome://browser/skin/menu-forward-XP.png                         os=WINNT osversion<6
 % override chrome://browser/skin/pageInfo.png                         chrome://browser/skin/pageInfo-XP.png                             os=WINNT osversion<6
-% override chrome://browser/skin/downloads/buttons.png                chrome://browser/skin/downloads/buttons-XP.png                    os=WINNT osversion<6
 % override chrome://browser/skin/feeds/feedIcon.png                   chrome://browser/skin/feeds/feedIcon-XP.png                       os=WINNT osversion<6
 % override chrome://browser/skin/feeds/feedIcon16.png                 chrome://browser/skin/feeds/feedIcon16-XP.png                     os=WINNT osversion<6
 % override chrome://browser/skin/places/query.png                     chrome://browser/skin/places/query-XP.png                         os=WINNT osversion<6
 % override chrome://browser/skin/places/bookmarksMenu.png             chrome://browser/skin/places/bookmarksMenu-XP.png                 os=WINNT osversion<6
 % override chrome://browser/skin/places/bookmarksToolbar.png          chrome://browser/skin/places/bookmarksToolbar-XP.png              os=WINNT osversion<6
 % override chrome://browser/skin/places/bookmarksToolbar-menuPanel.png  chrome://browser/skin/places/bookmarksToolbar-menuPanel-XP.png  os=WINNT osversion<6
 % override chrome://browser/skin/places/calendar.png                  chrome://browser/skin/places/calendar-XP.png                      os=WINNT osversion<6
 % override chrome://browser/skin/places/toolbarDropMarker.png         chrome://browser/skin/places/toolbarDropMarker-XP.png             os=WINNT osversion<6
--- a/build/clang-plugin/clang-plugin.cpp
+++ b/build/clang-plugin/clang-plugin.cpp
@@ -14,16 +14,17 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendPluginRegistry.h"
 #include "clang/Frontend/MultiplexConsumer.h"
 #include "clang/Sema/Sema.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include <memory>
+#include <iterator>
 
 #define CLANG_VERSION_FULL (CLANG_VERSION_MAJOR * 100 + CLANG_VERSION_MINOR)
 
 using namespace llvm;
 using namespace clang;
 
 #if CLANG_VERSION_FULL >= 306
 typedef std::unique_ptr<ASTConsumer> ASTConsumerPtr;
@@ -256,17 +257,18 @@ bool isInIgnoredNamespaceForImplicitCtor
          Name.substr(0, 4) == "icu_" || // icu
          Name == "google" ||            // protobuf
          Name == "google_breakpad" ||   // breakpad
          Name == "soundtouch" ||        // libsoundtouch
          Name == "stagefright" ||       // libstagefright
          Name == "MacFileUtilities" ||  // MacFileUtilities
          Name == "dwarf2reader" ||      // dwarf2reader
          Name == "arm_ex_to_module" ||  // arm_ex_to_module
-         Name == "testing";             // gtest
+         Name == "testing" ||           // gtest
+         Name == "Json";                // jsoncpp
 }
 
 bool isInIgnoredNamespaceForImplicitConversion(const Decl *Declaration) {
   std::string Name = getDeclarationNamespace(Declaration);
   if (Name == "") {
     return false;
   }
 
@@ -828,23 +830,35 @@ AST_MATCHER(QualType, isFloat) { return 
 
 /// This matcher will match locations in system headers.  This is adopted from
 /// isExpansionInSystemHeader in newer clangs, but modified in order to work
 /// with old clangs that we use on infra.
 AST_MATCHER(BinaryOperator, isInSystemHeader) {
   return ASTIsInSystemHeader(Finder->getASTContext(), Node);
 }
 
-/// This matcher will match locations in SkScalar.h.  This header contains a
-/// known NaN-testing expression which we would like to whitelist.
-AST_MATCHER(BinaryOperator, isInSkScalarDotH) {
+/// This matcher will match a list of files.  These files contain
+/// known NaN-testing expressions which we would like to whitelist.
+AST_MATCHER(BinaryOperator, isInWhitelistForNaNExpr) {
+  const char* whitelist[] = {
+    "SkScalar.h",
+    "json_writer.cpp"
+  };
+
   SourceLocation Loc = Node.getOperatorLoc();
   auto &SourceManager = Finder->getASTContext().getSourceManager();
   SmallString<1024> FileName = SourceManager.getFilename(Loc);
-  return llvm::sys::path::rbegin(FileName)->equals("SkScalar.h");
+
+  for (auto itr = std::begin(whitelist); itr != std::end(whitelist); itr++) {
+    if (llvm::sys::path::rbegin(FileName)->equals(*itr)) {
+      return true;
+    }
+  }
+
+  return false;
 }
 
 /// This matcher will match all accesses to AddRef or Release methods.
 AST_MATCHER(MemberExpr, isAddRefOrRelease) {
   ValueDecl *Member = Node.getMemberDecl();
   CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member);
   if (Method) {
     const auto &Name = getNameChecked(Method);
@@ -1192,17 +1206,17 @@ DiagnosticsMatcher::DiagnosticsMatcher()
 
   AstMatcher.addMatcher(
       binaryOperator(
           allOf(binaryEqualityOperator(),
                 hasLHS(hasIgnoringParenImpCasts(
                     declRefExpr(hasType(qualType((isFloat())))).bind("lhs"))),
                 hasRHS(hasIgnoringParenImpCasts(
                     declRefExpr(hasType(qualType((isFloat())))).bind("rhs"))),
-                unless(anyOf(isInSystemHeader(), isInSkScalarDotH()))))
+                unless(anyOf(isInSystemHeader(), isInWhitelistForNaNExpr()))))
           .bind("node"),
       &NaNExpr);
 
   // First, look for direct parents of the MemberExpr.
   AstMatcher.addMatcher(
       callExpr(
           callee(functionDecl(hasNoAddRefReleaseOnReturnAttr()).bind("func")),
           hasParent(memberExpr(isAddRefOrRelease(), hasParent(callExpr()))
--- a/caps/tests/mochitest/chrome.ini
+++ b/caps/tests/mochitest/chrome.ini
@@ -2,11 +2,8 @@
 skip-if = buildapp == 'b2g' || os == 'android'
 support-files =
   file_disableScript.html
   !/caps/tests/mochitest/file_disableScript.html
 
 [test_bug995943.xul]
 [test_addonMayLoad.html]
 [test_disableScript.xul]
-[test_principal_jarprefix_origin_appid_appstatus.html]
-# jarPrefix test doesn't work on Windows, see bug 776296.
-skip-if = true ### Bug 1255339: blacklist because no more mozApps
deleted file mode 100644
--- a/caps/tests/mochitest/test_principal_jarprefix_origin_appid_appstatus.html
+++ /dev/null
@@ -1,503 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=758258
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for nsIPrincipal jarPrefix, origin, appStatus and appId</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=758258">Mozilla Bug 758258</a>
-<p id="display"></p>
-<div id="content">
-
-</div>
-<pre id="test">
-<script type="application/javascript;version=1.7">
-
-/** Test for Bug 758258 **/
-
-var Ci = Components.interfaces;
-SimpleTest.waitForExplicitFinish();
-if (navigator.userAgent.indexOf("Mac OS X 10.10") != -1) {
-  SimpleTest.expectAssertions(0, 4);
-}
-
-/*
- * gData is an array of objects. Each object represents a test case.
- * - app: gives the app manifest URL, will set mozapp to it on the iframe;
- * - origin: gives the origin of the iframe. This is the URL thas is going to
- *           to be passed as iframe.src but also the expected principal's
- *           origin.
- * - isapp: tells if the iframe is really a mozapp. If the manifest url isn't
- *          valid, the iframe will not be considered as a mozapp.
- * - browser: say if the iframe should be a mozbrowser. This is implicit when
- *            app is set.
- * - isolated: if origin isolation is enabled with browser frames.  Defaults to
- *             true if unset.
- * - test: an array of tests to run for this test case:
- *   - eo-unique: the extendedOrigin of the prinicpal must be unique in the
- *                current list.
- *   - eo-as-last: the extendedOrigin of the principal must be the same as the
- *                 last added to the list.
- */
-var gData = [
-  {
-    app: "http://example.org/manifest.webapp",
-    src: "http://example.org/",
-    isapp: true,
-    test: [ "eo-unique" ],
-  },
-  {
-    app: "https://example.com/manifest.webapp",
-    src: "https://example.com/",
-    isapp: true,
-    test: [ "eo-unique" ],
-  },
-  {
-    app: "http://test1.example.org/manifest.webapp",
-    src: "http://test1.example.org/",
-    isapp: true,
-    test: [ "eo-unique" ],
-  },
-  {
-    app: "http://test1.example.org:8000/manifest.webapp",
-    src: "http://test1.example.org:8000/",
-    isapp: true,
-    test: [ "eo-unique" ],
-  },
-  {
-    app: "http://sub1.test1.example.org/manifest.webapp",
-    src: "http://sub1.test1.example.org/",
-    isapp: true,
-    test: [ "eo-unique" ],
-  },
-// WebApps implementation doesn't allow apps with the same origin. Sad...
-//  {
-//    app: "http://example.org/foo/manifest.webapp",
-//    src: "http://example.org/",
-//    isapp: true,
-//    test: [ "eo-unique" ],
-//  },
-//  {
-//    app: "http://example.org/bar/manifest.webapp",
-//    src: "http://example.org/",
-//    isapp: true,
-//    test: [ "eo-unique" ],
-//  },
-  {
-    src: "http://example.org/",
-    isapp: false,
-    test: [ "eo-unique" ],
-  },
-  {
-    browser: true,
-    src: "http://example.org/",
-    isapp: false,
-    test: [ "eo-unique" ],
-  },
-  {
-    app: "http://example.org/wedonthaveanyappinthatdirectory/manifest.webapp",
-    src: "http://example.org/",
-    isapp: false,
-    // TODO: this is a browser because we need apps to be browser and it's not
-    // an app because the manifest is invalid. Ideally, it should not be a
-    // browser.
-    browser: true,
-    test: [ "eo-as-last" ],
-  },
-//  {
-//    app: "http://example.org/manifest.webapp",
-//    src: "data:text/html,foobar",
-//    test: [ "todo-src" ],
-//  },
-//  {
-//    app: "http://example.org/manifest.webapp",
-//    src: "data:text/html,foobar2",
-//    test: [ "todo-src" ],
-//  },
-  {
-    src: "file:///",
-    isapp: false,
-    test: [ "eo-unique" ],
-  },
-  {
-    src: "file:///tmp/",
-    isapp: false,
-    test: [ "eo-unique" ],
-  },
-  {
-    app: "http://example.org/manifest.webapp",
-    src: "file:///",
-    isapp: true,
-    test: [ "eo-unique", "in-app-not-installed" ],
-  },
-  {
-    app: "http://example.org/manifest.webapp",
-    src: "file:///tmp/",
-    isapp: true,
-    test: [ "eo-unique", "in-app-not-installed" ],
-  },
-  // iframe inside an app is part of the app.
-  {
-    app: "http://example.org/manifest.webapp",
-    src: "http://example.org/",
-    isapp: true,
-    child: {
-      src: "http://example.org/chrome/",
-      isapp: true
-    },
-    test: [ "child-has-same-eo" ],
-  },
-  // app A inside app B aren't the same app.
-  {
-    app: "http://example.org/manifest.webapp",
-    src: "http://example.org/",
-    isapp: true,
-    child: {
-      app: "https://example.com/manifest.webapp",
-      src: "https://example.com/chrome/",
-      isapp: true
-    },
-    test: [ "child-has-different-eo", "child-has-same-appstatus", "child-has-different-appid" ],
-  },
-  // app A inside app A are the same app.
-  {
-    app: "http://example.org/manifest.webapp",
-    src: "http://example.org/",
-    isapp: true,
-    child: {
-      app: "http://example.org/manifest.webapp",
-      src: "http://example.org/chrome/",
-      isapp: true
-    },
-    test: [ "child-has-same-eo" ],
-  },
-  // app inside a regular iframe is an app.
-  {
-    src: "http://example.org/",
-    isapp: false,
-    child: {
-      app: "http://example.org/manifest.webapp",
-      src: "http://example.org/chrome/",
-      isapp: true
-    },
-    test: [ "child-has-different-eo", "child-has-different-appstatus", "child-has-different-appid" ],
-  },
-  // browser inside app is a browser, has appid but isn't installed.
-  {
-    src: "http://example.org/",
-    app: "http://example.org/manifest.webapp",
-    isapp: true,
-    child: {
-      src: "http://example.org/chrome/",
-      isapp: false,
-      browser: true,
-    },
-    test: [ "child-has-different-eo", "child-has-different-appstatus", "child-has-same-appid" ],
-  },
-  // browser inside a browser are two browsers
-  {
-    src: "http://example.org/",
-    isapp: false,
-    browser: true,
-    child: {
-      src: "http://example.org/chrome/",
-      isapp: false,
-      browser: true,
-    },
-    test: [ "child-has-same-eo" ],
-  },
-  // browser inside a browser are two browsers
-  {
-    src: "http://example.org/",
-    isapp: false,
-    browser: true,
-    child: {
-      src: "https://example.com/chrome/",
-      isapp: false,
-      browser: true,
-    },
-    test: [ "child-has-different-eo", "child-has-same-appstatus", "child-has-same-appid" ],
-  },
-  // iframe containing a browser
-  {
-    src: "http://example.org/",
-    isapp: false,
-    browser: false,
-    child: {
-      src: "http://example.org/chrome/",
-      isapp: false,
-      browser: true,
-    },
-    test: [ "child-has-different-eo", "child-has-same-appstatus", "child-has-same-appid" ],
-  },
-  // browser containing an iframe that is part of the browser
-  {
-    src: "http://example.org/",
-    isapp: false,
-    browser: true,
-    child: {
-      src: "http://example.org/chrome/",
-      isapp: false,
-      inIsolatedMozBrowser: true,
-    },
-    test: [ "child-has-same-eo" ],
-  },
-  // iframe containing a browser with isolation disabled
-  // (only chrome documents can disable isolation)
-  {
-    src: "http://example.org/",
-    isapp: false,
-    browser: false,
-    child: {
-      src: "http://example.org/chrome/",
-      isapp: false,
-      browser: true,
-      isolated: false,
-      inIsolatedMozBrowser: true,
-    },
-    test: [ "child-has-different-eo" ],
-  },
-  // browser with isolation disabled containing an iframe that is part of the browser
-  {
-    src: "http://example.org/",
-    isapp: false,
-    browser: true,
-    isolated: false,
-    child: {
-      src: "http://example.org/chrome/",
-      isapp: false,
-      inIsolatedMozBrowser: false,
-    },
-    test: [ "child-has-same-eo" ],
-  },
-  // iframe with isolation enabled containing an iframe with isolation disabled
-  // (isolated only has an effect on browsers)
-  {
-    src: "http://example.org/",
-    isapp: false,
-    browser: false,
-    isolated: true,
-    child: {
-      src: "http://example.org/chrome/",
-      isapp: false,
-      browser: false,
-      isolated: false,
-    },
-    test: [ "child-has-same-eo" ],
-  },
-];
-
-// The list of all data ids generated by this test.
-var eoList = [];
-
-var content = document.getElementById('content');
-var checkedCount = 0;
-var checksTodo = gData.length;
-
-function checkIFrame(aFrame, data) {
-  var principal = aFrame.contentDocument.nodePrincipal;
-
-  if (!data.test) {
-    data.test = [];
-  }
-
-  if (navigator.platform.indexOf("Mac") != -1) {
-    is(principal.URI.spec,
-       data.src.replace('file:///tmp/', 'file:///private/tmp/'),
-       'the correct URL should have been loaded');
-  } else {
-    is(principal.URI.spec, data.src,
-       'the correct URL should have been loaded');
-  }
-
-  if (data.isapp) {
-    if (data.test.indexOf("in-app-not-installed") != -1) {
-      is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED, 'this should not be an installed app');
-    } else {
-      is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_INSTALLED, 'this should be an installed app');
-    }
-  } else {
-    is(principal.appStatus, Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED,
-       'this should not be an installed app');
-    is(principal.appId, Ci.nsIScriptSecurityManager.NO_APP_ID,
-       "principals from non-installed app should have NO_APP_ID");
-  }
-
-  if (!data.isapp && !data.browser ||
-      (data.browser && data.isolated === false)) {
-    is(principal.jarPrefix, "",
-       "jarPrefix should return an empty string for non-app, non-browsers, " +
-       "and browsers with isolation disabled");
-  } else {
-    isnot(principal.jarPrefix, "",
-          "jarPrefix should not return an empty string for apps or browsers " +
-          "with isolation enabled");
-  }
-
-  if (data.test.indexOf("eo-unique") != -1) {
-    is(eoList.indexOf(principal.jarPrefix + principal.origin), -1,
-       "extended origin should be unique");
-  }
-  if (data.test.indexOf("eo-as-last") != -1) {
-    is(principal.jarPrefix + principal.origin, eoList[eoList.length-1],
-       "extended origin should be the same as the last inserted one");
-  }
-
-  let isolationExpected = false;
-  if (data.isolated !== false) {
-    isolationExpected = !!data.browser;
-  }
-  is(principal.isInIsolatedMozBrowserElement, isolationExpected,
-     "check principal.isInIsolatedMozBrowserElement");
-
-  if (data.child) {
-    let childPrincipal = aFrame.contentWindow.frames[0].document.nodePrincipal;
-
-    if (data.child.isapp) {
-      is(childPrincipal.appStatus, Ci.nsIPrincipal.APP_STATUS_INSTALLED,
-         "child should be an installed app");
-    }
-
-    let childIsolationExpected = false;
-    if (data.child.isolated !== false) {
-      childIsolationExpected = !!data.child.browser;
-    }
-    if (data.child.inIsolatedMozBrowser !== undefined) {
-      childIsolationExpected = data.child.inIsolatedMozBrowser;
-    }
-    is(childPrincipal.isInIsolatedMozBrowserElement, childIsolationExpected,
-       "check childPrincipal.isInIsolatedMozBrowserElement");
-
-    if (data.test.indexOf("child-has-same-eo") != -1) {
-      is(childPrincipal.jarPrefix + childPrincipal.origin,
-         principal.jarPrefix + principal.origin,
-         "child should have the same extended origin as parent");
-      is(childPrincipal.appStatus, principal.appStatus,
-         "child should have the same appStatus if it has the same extended origin");
-      is(childPrincipal.appId, principal.appId,
-         "child should have the same appId if it has the same extended origin");
-    }
-
-    if (data.test.indexOf("child-has-different-eo") != -1) {
-      isnot(childPrincipal.jarPrefix + childPrincipal.origin,
-            principal.jarPrefix + principal.origin,
-            "child should not have the same extended origin as parent");
-    }
-
-    if (data.test.indexOf("child-has-same-appstatus") != -1) {
-      is(childPrincipal.appStatus, principal.appStatus,
-         "childPrincipal and parent principal should have the same appStatus");
-    }
-
-    if (data.test.indexOf("child-has-different-appstatus") != -1) {
-      isnot(childPrincipal.appStatus, principal.appStatus,
-            "childPrincipal and parent principal should not have the same appStatus");
-    }
-
-    if (data.test.indexOf("child-has-same-appid") != -1) {
-      is(childPrincipal.appId, principal.appId,
-         "childPrincipal and parent principal should have the same appId");
-    }
-
-    if (data.test.indexOf("child-has-different-appid") != -1) {
-      isnot(childPrincipal.appId, principal.appId,
-            "childPrincipal and parent principal should have different appId");
-    }
-  }
-
-  eoList.push(principal.jarPrefix + principal.origin);
-
-  checkedCount++;
-  if (checkedCount == checksTodo) {
-    SpecialPowers.removePermission("browser", "http://example.org");
-    SpecialPowers.removePermission("embed-apps", "http://example.org");
-    SimpleTest.finish();
-  } else {
-    gTestRunner.next();
-  }
-}
-
-is('appStatus' in document.nodePrincipal, true,
-   'appStatus should be present in nsIPrincipal');
-is('jarPrefix' in document.nodePrincipal, true,
-   'jarPrefix should be present in nsIPrincipal');
-is('origin' in document.nodePrincipal, true,
-   'origin should be present in nsIPrincipal');
-is('appId' in document.nodePrincipal, true,
-   'appId should be present in nsIPrincipal');
-
-function runTest() {
-  // We want to use a generator. Those only work in a one level stack so we
-  // can't use .forEach() here.
-  for (var i=0; i<gData.length; ++i) {
-    let data = gData[i];
-
-    var iframe = document.createElement('iframe');
-    iframe.check = function() {
-      checkIFrame(this, data);
-    };
-    iframe.addChild = function() {
-      SpecialPowers.addPermission("browser", true, iframe.contentDocument);
-      SpecialPowers.addPermission("embed-apps", true, iframe.contentDocument);
-
-      var childFrame = document.createElement('iframe');
-
-      if (data.child.app) {
-        childFrame.setAttribute('mozapp', data.child.app)
-        childFrame.setAttribute('mozbrowser', '');
-      } else if (data.child.browser) {
-        childFrame.setAttribute('mozbrowser', '');
-      }
-
-      if (data.child.isolated === false) {
-        childFrame.setAttribute("noisolation", "");
-      }
-
-      childFrame.src = data.child.src;
-
-      this.removeEventListener('load', this.addChild.bind(this));
-      childFrame.addEventListener('load', this.check.bind(this));
-
-      this.contentDocument.body.appendChild(childFrame);
-    };
-
-    if (data.app) {
-      iframe.setAttribute('mozapp', data.app);
-      iframe.setAttribute('mozbrowser', '');
-    } else if (data.browser) {
-      iframe.setAttribute('mozbrowser', '');
-    }
-
-    if (data.isolated === false) {
-      iframe.setAttribute("noisolation", "");
-    }
-
-    iframe.src = data.src;
-
-    if (data.child) {
-      iframe.addEventListener('load', iframe.addChild.bind(iframe));
-    } else {
-      iframe.addEventListener('load', iframe.check.bind(iframe));
-    }
-
-    content.appendChild(iframe);
-
-    yield;
-  }
-}
-
-var gTestRunner = runTest();
-
-SpecialPowers.pushPrefEnv({"set": [
-  ["dom.mozBrowserFramesEnabled", true],
-]}, function() { gTestRunner.next(); });
-
-</script>
-</pre>
-</body>
-</html>
--- a/devtools/client/debugger/new/bundle.js
+++ b/devtools/client/debugger/new/bundle.js
@@ -1,9 +1,9 @@
-// Generated from: bea6f2d2e0efef114265f177def09806e7f69784 Merge pull request #843 from jlongster/fix-css-var
+// Generated from: 873b94a2fc86b95fb4ff2ba728b50e5f137a909b chore(package): update eslint-plugin-flowtype to version 2.20.0 (#895)
 
 var Debugger =
 /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
 /******/
 /******/ 	// The require function
 /******/ 	function __webpack_require__(moduleId) {
@@ -62,16 +62,18 @@ var Debugger =
 	var combineReducers = _require.combineReducers;
 	
 	var _require2 = __webpack_require__(15);
 	
 	var Provider = _require2.Provider;
 	
 	var ReactDOM = __webpack_require__(25);
 	var React = __webpack_require__(17);
+	var dom = React.DOM;
+	
 	
 	var DevToolsUtils = __webpack_require__(27);
 	var AppConstants = __webpack_require__(41).AppConstants;
 	
 	var _require3 = __webpack_require__(45);
 	
 	var injectGlobals = _require3.injectGlobals;
 	
@@ -79,46 +81,46 @@ var Debugger =
 	
 	var isEnabled = _require4.isEnabled;
 	var isFirefoxPanel = _require4.isFirefoxPanel;
 	var getValue = _require4.getValue;
 	var isDevelopment = _require4.isDevelopment;
 	var setConfig = _require4.setConfig;
 	
 	
-	setConfig(({"environment":"firefox-panel","baseWorkerURL":"resource://devtools/client/debugger/new/","logging":false,"clientLogging":false,"features":{"tabs":true}}));
+	setConfig(({"environment":"firefox-panel","baseWorkerURL":"resource://devtools/client/debugger/new/","logging":false,"clientLogging":false,"features":{"tabs":true,"sourceMaps":true}}));
 	
 	// Set various flags before requiring app code.
 	if (isEnabled("logging.client")) {
 	  DevToolsUtils.dumpn.wantLogging = true;
 	}
 	
-	var _require5 = __webpack_require__(96);
+	var _require5 = __webpack_require__(98);
 	
 	var getClient = _require5.getClient;
 	var connectClients = _require5.connectClients;
 	var startDebugging = _require5.startDebugging;
 	
-	var firefox = __webpack_require__(98);
-	var configureStore = __webpack_require__(178);
-	var reducers = __webpack_require__(188);
-	var selectors = __webpack_require__(199);
-	
-	var Tabs = __webpack_require__(200);
-	var App = __webpack_require__(206);
+	var firefox = __webpack_require__(100);
+	var configureStore = __webpack_require__(181);
+	var reducers = __webpack_require__(191);
+	var selectors = __webpack_require__(202);
+	
+	var LandingPage = __webpack_require__(203);
+	var App = __webpack_require__(210);
 	
 	var createStore = configureStore({
 	  log: getValue("logging.actions"),
 	  makeThunkArgs: (args, state) => {
 	    return Object.assign({}, args, { client: getClient(state) });
 	  }
 	});
 	
 	var store = createStore(combineReducers(reducers));
-	var actions = bindActionCreators(__webpack_require__(209), store.dispatch);
+	var actions = bindActionCreators(__webpack_require__(213), store.dispatch);
 	
 	if (isDevelopment()) {
 	  AppConstants.DEBUG_JS_MODULES = true;
 	  injectGlobals({ store });
 	}
 	
 	// Expose the bound actions so external things can do things like
 	// selecting a source.
@@ -130,17 +132,20 @@ var Debugger =
 	function renderRoot(component) {
 	  var mount = document.querySelector("#mount");
 	
 	  // bail in test environments that do not have a mount
 	  if (!mount) {
 	    return;
 	  }
 	
-	  ReactDOM.render(React.createElement(Provider, { store }, React.createElement(component)), mount);
+	  ReactDOM.render(React.createElement(Provider, { store }, dom.div({
+	    className: "theme-light",
+	    style: { flex: 1 }
+	  }, React.createElement(component))), mount);
 	}
 	
 	function unmountRoot() {
 	  var mount = document.querySelector("#mount");
 	  ReactDOM.unmountComponentAtNode(mount);
 	}
 	
 	function getTargetFromQuery() {
@@ -164,40 +169,40 @@ var Debugger =
 	if (connTarget) {
 	  startDebugging(connTarget, actions).then(tabs => {
 	    actions.newTabs(tabs);
 	    actions.selectTab({ id: connTarget.param });
 	    renderRoot(App);
 	  });
 	} else if (isFirefoxPanel()) {
 	  (function () {
-	    var sourceMap = __webpack_require__(211);
+	    var sourceMap = __webpack_require__(215);
 	
 	    module.exports = {
-	      bootstrap: _ref => {
+	      bootstrap: (_ref) => {
 	        var threadClient = _ref.threadClient;
 	        var tabTarget = _ref.tabTarget;
 	
 	        firefox.setThreadClient(threadClient);
 	        firefox.setTabTarget(tabTarget);
 	        renderRoot(App);
 	        return firefox.initPage(actions);
 	      },
 	      destroy: () => {
 	        unmountRoot();
-	        sourceMap.destroy();
+	        sourceMap.destroyWorker();
 	      },
 	      store: store,
 	      actions: actions,
 	      selectors: selectors,
 	      client: firefox.clientCommands
 	    };
 	  })();
 	} else {
-	  renderRoot(Tabs);
+	  renderRoot(LandingPage);
 	  connectClients(tabs => actions.newTabs(tabs));
 	}
 
 /***/ },
 /* 2 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
@@ -514,52 +519,51 @@ var Debugger =
 	  }, _ref2[_symbolObservable2["default"]] = observable, _ref2;
 	}
 
 /***/ },
 /* 4 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var getPrototype = __webpack_require__(5),
-	    isHostObject = __webpack_require__(6),
 	    isObjectLike = __webpack_require__(7);
 	
 	/** `Object#toString` result references. */
 	var objectTag = '[object Object]';
 	
 	/** Used for built-in method references. */
-	var objectProto = Object.prototype;
+	var funcProto = Function.prototype,
+	    objectProto = Object.prototype;
 	
 	/** Used to resolve the decompiled source of functions. */
-	var funcToString = Function.prototype.toString;
+	var funcToString = funcProto.toString;
 	
 	/** Used to check objects for own properties. */
 	var hasOwnProperty = objectProto.hasOwnProperty;
 	
 	/** Used to infer the `Object` constructor. */
 	var objectCtorString = funcToString.call(Object);
 	
 	/**
 	 * Used to resolve the
-	 * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+	 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 	 * of values.
 	 */
 	var objectToString = objectProto.toString;
 	
 	/**
 	 * Checks if `value` is a plain object, that is, an object created by the
 	 * `Object` constructor or one with a `[[Prototype]]` of `null`.
 	 *
 	 * @static
 	 * @memberOf _
 	 * @since 0.8.0
 	 * @category Lang
 	 * @param {*} value The value to check.
-	 * @returns {boolean} Returns `true` if `value` is a plain object,
-	 *  else `false`.
+	 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
 	 * @example
 	 *
 	 * function Foo() {
 	 *   this.a = 1;
 	 * }
 	 *
 	 * _.isPlainObject(new Foo);
 	 * // => false
@@ -569,77 +573,62 @@ var Debugger =
 	 *
 	 * _.isPlainObject({ 'x': 0, 'y': 0 });
 	 * // => true
 	 *
 	 * _.isPlainObject(Object.create(null));
 	 * // => true
 	 */
 	function isPlainObject(value) {
-	  if (!isObjectLike(value) ||
-	      objectToString.call(value) != objectTag || isHostObject(value)) {
+	  if (!isObjectLike(value) || objectToString.call(value) != objectTag) {
 	    return false;
 	  }
 	  var proto = getPrototype(value);
 	  if (proto === null) {
 	    return true;
 	  }
 	  var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
 	  return (typeof Ctor == 'function' &&
 	    Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);
 	}
 	
 	module.exports = isPlainObject;
 
 
 /***/ },
 /* 5 */
-/***/ function(module, exports) {
-
-	/* Built-in method references for those with the same name as other `lodash` methods. */
-	var nativeGetPrototype = Object.getPrototypeOf;
-	
-	/**
-	 * Gets the `[[Prototype]]` of `value`.
-	 *
-	 * @private
-	 * @param {*} value The value to query.
-	 * @returns {null|Object} Returns the `[[Prototype]]`.
-	 */
-	function getPrototype(value) {
-	  return nativeGetPrototype(Object(value));
-	}
+/***/ function(module, exports, __webpack_require__) {
+
+	var overArg = __webpack_require__(6);
+	
+	/** Built-in value references. */
+	var getPrototype = overArg(Object.getPrototypeOf, Object);
 	
 	module.exports = getPrototype;
 
 
 /***/ },
 /* 6 */
 /***/ function(module, exports) {
 
 	/**
-	 * Checks if `value` is a host object in IE < 9.
-	 *
-	 * @private
-	 * @param {*} value The value to check.
-	 * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
-	 */
-	function isHostObject(value) {
-	  // Many host objects are `Object` objects that can coerce to strings
-	  // despite having improperly defined `toString` methods.
-	  var result = false;
-	  if (value != null && typeof value.toString != 'function') {
-	    try {
-	      result = !!(value + '');
-	    } catch (e) {}
-	  }
-	  return result;
-	}
-	
-	module.exports = isHostObject;
+	 * Creates a unary function that invokes `func` with its argument transformed.
+	 *
+	 * @private
+	 * @param {Function} func The function to wrap.
+	 * @param {Function} transform The argument transform.
+	 * @returns {Function} Returns the new function.
+	 */
+	function overArg(func, transform) {
+	  return function(arg) {
+	    return func(transform(arg));
+	  };
+	}
+	
+	module.exports = overArg;
 
 
 /***/ },
 /* 7 */
 /***/ function(module, exports) {
 
 	/**
 	 * Checks if `value` is object-like. A value is object-like if it's not `null`
@@ -661,17 +650,17 @@ var Debugger =
 	 *
 	 * _.isObjectLike(_.noop);
 	 * // => false
 	 *
 	 * _.isObjectLike(null);
 	 * // => false
 	 */
 	function isObjectLike(value) {
-	  return !!value && typeof value == 'object';
+	  return value != null && typeof value == 'object';
 	}
 	
 	module.exports = isObjectLike;
 
 
 /***/ },
 /* 8 */
 /***/ function(module, exports, __webpack_require__) {
@@ -1575,25 +1564,24 @@ var Debugger =
 	      Connect.prototype.componentWillUpdate = function componentWillUpdate() {
 	        if (this.version === version) {
 	          return;
 	        }
 	
 	        // We are hot reloading!
 	        this.version = version;
 	        this.trySubscribe();
-	        // this.clearCache();
+	        this.clearCache();
 	      };
 	    }
 	
 	    return (0, _hoistNonReactStatics2["default"])(Connect, WrappedComponent);
 	  };
 	}
 
-
 /***/ },
 /* 21 */
 /***/ function(module, exports) {
 
 	"use strict";
 	
 	exports.__esModule = true;
 	exports["default"] = shallowEqual;
@@ -8643,17 +8631,17 @@ var Debugger =
 	    window[field] = value;
 	  }
 	}
 	
 	function injectGlobals(_ref) {
 	  var store = _ref.store;
 	
 	  debugGlobal("store", store);
-	  debugGlobal("injectDebuggee", __webpack_require__(95));
+	  debugGlobal("injectDebuggee", __webpack_require__(97));
 	  debugGlobal("serializeStore", () => {
 	    return JSON.parse(JSON.stringify(store.getState()));
 	  });
 	}
 	
 	module.exports = {
 	  debugGlobal,
 	  injectGlobals
@@ -8742,17 +8730,17 @@ var Debugger =
 /***/ },
 /* 49 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var baseGet = __webpack_require__(50);
 	
 	/**
 	 * Gets the value at `path` of `object`. If the resolved value is
-	 * `undefined`, the `defaultValue` is used in its place.
+	 * `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.
@@ -8778,18 +8766,18 @@ var Debugger =
 	module.exports = get;
 
 
 /***/ },
 /* 50 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var castPath = __webpack_require__(51),
-	    isKey = __webpack_require__(93),
-	    toKey = __webpack_require__(94);
+	    isKey = __webpack_require__(95),
+	    toKey = __webpack_require__(96);
 	
 	/**
 	 * 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.
@@ -8835,21 +8823,19 @@ var Debugger =
 /***/ function(module, exports) {
 
 	/**
 	 * Checks if `value` is classified as an `Array` object.
 	 *
 	 * @static
 	 * @memberOf _
 	 * @since 0.1.0
-	 * @type {Function}
 	 * @category Lang
 	 * @param {*} value The value to check.
-	 * @returns {boolean} Returns `true` if `value` is correctly classified,
-	 *  else `false`.
+	 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 	 * @example
 	 *
 	 * _.isArray([1, 2, 3]);
 	 * // => true
 	 *
 	 * _.isArray(document.body.children);
 	 * // => false
 	 *
@@ -8863,63 +8849,101 @@ var Debugger =
 	
 	module.exports = isArray;
 
 
 /***/ },
 /* 53 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var memoize = __webpack_require__(54),
-	    toString = __webpack_require__(89);
+	var memoizeCapped = __webpack_require__(54),
+	    toString = __webpack_require__(90);
 	
 	/** Used to match property names within property paths. */
-	var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(\.|\[\])(?:\4|$))/g;
+	var reLeadingDot = /^\./,
+	    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 = memoize(function(string) {
+	var stringToPath = memoizeCapped(function(string) {
+	  string = toString(string);
+	
 	  var result = [];
-	  toString(string).replace(rePropName, function(match, number, quote, string) {
+	  if (reLeadingDot.test(string)) {
+	    result.push('');
+	  }
+	  string.replace(rePropName, function(match, number, quote, string) {
 	    result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
 	  });
 	  return result;
 	});
 	
 	module.exports = stringToPath;
 
 
 /***/ },
 /* 54 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var MapCache = __webpack_require__(55);
-	
-	/** Used as the `TypeError` message for "Functions" methods. */
+	var memoize = __webpack_require__(55);
+	
+	/** 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;
+
+
+/***/ },
+/* 55 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var MapCache = __webpack_require__(56);
+	
+	/** 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/6.0/#sec-properties-of-the-map-prototype-object)
+	 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
 	 * method interface of `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.
@@ -8956,38 +8980,38 @@ var Debugger =
 	    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);
+	    memoized.cache = cache.set(key, result) || cache;
 	    return result;
 	  };
 	  memoized.cache = new (memoize.Cache || MapCache);
 	  return memoized;
 	}
 	
-	// Assign cache to `_.memoize`.
+	// Expose `MapCache`.
 	memoize.Cache = MapCache;
 	
 	module.exports = memoize;
 
 
 /***/ },
-/* 55 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var mapCacheClear = __webpack_require__(56),
-	    mapCacheDelete = __webpack_require__(83),
-	    mapCacheGet = __webpack_require__(86),
-	    mapCacheHas = __webpack_require__(87),
-	    mapCacheSet = __webpack_require__(88);
+/* 56 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var mapCacheClear = __webpack_require__(57),
+	    mapCacheDelete = __webpack_require__(84),
+	    mapCacheGet = __webpack_require__(87),
+	    mapCacheHas = __webpack_require__(88),
+	    mapCacheSet = __webpack_require__(89);
 	
 	/**
 	 * Creates a map cache object to store key-value pairs.
 	 *
 	 * @private
 	 * @constructor
 	 * @param {Array} [entries] The key-value pairs to cache.
 	 */
@@ -9008,50 +9032,51 @@ var Debugger =
 	MapCache.prototype.get = mapCacheGet;
 	MapCache.prototype.has = mapCacheHas;
 	MapCache.prototype.set = mapCacheSet;
 	
 	module.exports = MapCache;
 
 
 /***/ },
-/* 56 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var Hash = __webpack_require__(57),
-	    ListCache = __webpack_require__(74),
-	    Map = __webpack_require__(82);
+/* 57 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var Hash = __webpack_require__(58),
+	    ListCache = __webpack_require__(75),
+	    Map = __webpack_require__(83);
 	
 	/**
 	 * 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;
 
 
 /***/ },
-/* 57 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var hashClear = __webpack_require__(58),
-	    hashDelete = __webpack_require__(70),
-	    hashGet = __webpack_require__(71),
-	    hashHas = __webpack_require__(72),
-	    hashSet = __webpack_require__(73);
+/* 58 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var hashClear = __webpack_require__(59),
+	    hashDelete = __webpack_require__(71),
+	    hashGet = __webpack_require__(72),
+	    hashHas = __webpack_require__(73),
+	    hashSet = __webpack_require__(74);
 	
 	/**
 	 * Creates a hash object.
 	 *
 	 * @private
 	 * @constructor
 	 * @param {Array} [entries] The key-value pairs to cache.
 	 */
@@ -9072,53 +9097,54 @@ var Debugger =
 	Hash.prototype.get = hashGet;
 	Hash.prototype.has = hashHas;
 	Hash.prototype.set = hashSet;
 	
 	module.exports = Hash;
 
 
 /***/ },
-/* 58 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var nativeCreate = __webpack_require__(59);
+/* 59 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var nativeCreate = __webpack_require__(60);
 	
 	/**
 	 * 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;
 
 
 /***/ },
-/* 59 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getNative = __webpack_require__(60);
+/* 60 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getNative = __webpack_require__(61);
 	
 	/* Built-in method references that are verified to be native. */
 	var nativeCreate = getNative(Object, 'create');
 	
 	module.exports = nativeCreate;
 
 
 /***/ },
-/* 60 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var baseIsNative = __webpack_require__(61),
-	    getValue = __webpack_require__(69);
+/* 61 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var baseIsNative = __webpack_require__(62),
+	    getValue = __webpack_require__(70);
 	
 	/**
 	 * 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`.
@@ -9127,39 +9153,39 @@ var Debugger =
 	  var value = getValue(object, key);
 	  return baseIsNative(value) ? value : undefined;
 	}
 	
 	module.exports = getNative;
 
 
 /***/ },
-/* 61 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isFunction = __webpack_require__(62),
-	    isHostObject = __webpack_require__(6),
-	    isMasked = __webpack_require__(64),
-	    isObject = __webpack_require__(63),
-	    toSource = __webpack_require__(68);
+/* 62 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isFunction = __webpack_require__(63),
+	    isMasked = __webpack_require__(65),
+	    isObject = __webpack_require__(64),
+	    toSource = __webpack_require__(69);
 	
 	/**
 	 * Used to match `RegExp`
-	 * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns).
+	 * [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 objectProto = Object.prototype;
+	var funcProto = Function.prototype,
+	    objectProto = Object.prototype;
 	
 	/** Used to resolve the decompiled source of functions. */
-	var funcToString = Function.prototype.toString;
+	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.*?') + '$'
@@ -9172,79 +9198,78 @@ var Debugger =
 	 * @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) || isHostObject(value)) ? reIsNative : reIsHostCtor;
+	  var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
 	  return pattern.test(toSource(value));
 	}
 	
 	module.exports = baseIsNative;
 
 
 /***/ },
-/* 62 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isObject = __webpack_require__(63);
+/* 63 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isObject = __webpack_require__(64);
 	
 	/** `Object#toString` result references. */
 	var funcTag = '[object Function]',
-	    genTag = '[object GeneratorFunction]';
+	    genTag = '[object GeneratorFunction]',
+	    proxyTag = '[object Proxy]';
 	
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
 	
 	/**
 	 * Used to resolve the
-	 * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+	 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 	 * of values.
 	 */
 	var objectToString = objectProto.toString;
 	
 	/**
 	 * 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 correctly classified,
-	 *  else `false`.
+	 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 	 * @example
 	 *
 	 * _.isFunction(_);
 	 * // => true
 	 *
 	 * _.isFunction(/abc/);
 	 * // => false
 	 */
 	function isFunction(value) {
 	  // The use of `Object#toString` avoids issues with the `typeof` operator
-	  // in Safari 8 which returns 'object' for typed array and weak map constructors,
-	  // and PhantomJS 1.9 which returns 'function' for `NodeList` instances.
+	  // in Safari 9 which returns 'object' for typed array and other constructors.
 	  var tag = isObject(value) ? objectToString.call(value) : '';
-	  return tag == funcTag || tag == genTag;
+	  return tag == funcTag || tag == genTag || tag == proxyTag;
 	}
 	
 	module.exports = isFunction;
 
 
 /***/ },
-/* 63 */
+/* 64 */
 /***/ function(module, exports) {
 
 	/**
 	 * Checks if `value` is the
-	 * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types)
+	 * [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`.
@@ -9259,27 +9284,27 @@ var Debugger =
 	 * _.isObject(_.noop);
 	 * // => true
 	 *
 	 * _.isObject(null);
 	 * // => false
 	 */
 	function isObject(value) {
 	  var type = typeof value;
-	  return !!value && (type == 'object' || type == 'function');
+	  return value != null && (type == 'object' || type == 'function');
 	}
 	
 	module.exports = isObject;
 
 
 /***/ },
-/* 64 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var coreJsData = __webpack_require__(65);
+/* 65 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var coreJsData = __webpack_require__(66);
 	
 	/** 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) : '';
 	}());
 	
 	/**
@@ -9292,73 +9317,62 @@ var Debugger =
 	function isMasked(func) {
 	  return !!maskSrcKey && (maskSrcKey in func);
 	}
 	
 	module.exports = isMasked;
 
 
 /***/ },
-/* 65 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var root = __webpack_require__(66);
+/* 66 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var root = __webpack_require__(67);
 	
 	/** Used to detect overreaching core-js shims. */
 	var coreJsData = root['__core-js_shared__'];
 	
 	module.exports = coreJsData;
 
 
 /***/ },
-/* 66 */
-/***/ function(module, exports, __webpack_require__) {
-
-	/* WEBPACK VAR INJECTION */(function(global) {var checkGlobal = __webpack_require__(67);
-	
-	/** Detect free variable `global` from Node.js. */
-	var freeGlobal = checkGlobal(typeof global == 'object' && global);
+/* 67 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var freeGlobal = __webpack_require__(68);
 	
 	/** Detect free variable `self`. */
-	var freeSelf = checkGlobal(typeof self == 'object' && self);
-	
-	/** Detect `this` as the global object. */
-	var thisGlobal = checkGlobal(typeof this == 'object' && this);
+	var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
 	
 	/** Used as a reference to the global object. */
-	var root = freeGlobal || freeSelf || thisGlobal || Function('return this')();
+	var root = freeGlobal || freeSelf || Function('return this')();
 	
 	module.exports = root;
-	
-	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
-
-/***/ },
-/* 67 */
-/***/ function(module, exports) {
-
-	/**
-	 * Checks if `value` is a global object.
-	 *
-	 * @private
-	 * @param {*} value The value to check.
-	 * @returns {null|Object} Returns `value` if it's a global object, else `null`.
-	 */
-	function checkGlobal(value) {
-	  return (value && value.Object === Object) ? value : null;
-	}
-	
-	module.exports = checkGlobal;
 
 
 /***/ },
 /* 68 */
 /***/ function(module, exports) {
 
+	/* 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, (function() { return this; }())))
+
+/***/ },
+/* 69 */
+/***/ function(module, exports) {
+
+	/** Used for built-in method references. */
+	var funcProto = Function.prototype;
+	
 	/** Used to resolve the decompiled source of functions. */
-	var funcToString = Function.prototype.toString;
+	var funcToString = funcProto.toString;
 	
 	/**
 	 * Converts `func` to its source code.
 	 *
 	 * @private
 	 * @param {Function} func The function to process.
 	 * @returns {string} Returns the source code.
 	 */
@@ -9373,17 +9387,17 @@ var Debugger =
 	  }
 	  return '';
 	}
 	
 	module.exports = toSource;
 
 
 /***/ },
-/* 69 */
+/* 70 */
 /***/ 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.
@@ -9392,41 +9406,43 @@ var Debugger =
 	function getValue(object, key) {
 	  return object == null ? undefined : object[key];
 	}
 	
 	module.exports = getValue;
 
 
 /***/ },
-/* 70 */
+/* 71 */
 /***/ 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) {
-	  return this.has(key) && delete this.__data__[key];
+	  var result = this.has(key) && delete this.__data__[key];
+	  this.size -= result ? 1 : 0;
+	  return result;
 	}
 	
 	module.exports = hashDelete;
 
 
 /***/ },
-/* 71 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var nativeCreate = __webpack_require__(59);
+/* 72 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var nativeCreate = __webpack_require__(60);
 	
 	/** 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. */
@@ -9449,20 +9465,20 @@ var Debugger =
 	  }
 	  return hasOwnProperty.call(data, key) ? data[key] : undefined;
 	}
 	
 	module.exports = hashGet;
 
 
 /***/ },
-/* 72 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var nativeCreate = __webpack_require__(59);
+/* 73 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var nativeCreate = __webpack_require__(60);
 	
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
 	
 	/** Used to check objects for own properties. */
 	var hasOwnProperty = objectProto.hasOwnProperty;
 	
 	/**
@@ -9478,52 +9494,53 @@ var Debugger =
 	  var data = this.__data__;
 	  return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
 	}
 	
 	module.exports = hashHas;
 
 
 /***/ },
-/* 73 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var nativeCreate = __webpack_require__(59);
+/* 74 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var nativeCreate = __webpack_require__(60);
 	
 	/** 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;
 
 
 /***/ },
-/* 74 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var listCacheClear = __webpack_require__(75),
-	    listCacheDelete = __webpack_require__(76),
-	    listCacheGet = __webpack_require__(79),
-	    listCacheHas = __webpack_require__(80),
-	    listCacheSet = __webpack_require__(81);
+/* 75 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var listCacheClear = __webpack_require__(76),
+	    listCacheDelete = __webpack_require__(77),
+	    listCacheGet = __webpack_require__(80),
+	    listCacheHas = __webpack_require__(81),
+	    listCacheSet = __webpack_require__(82);
 	
 	/**
 	 * Creates an list cache object.
 	 *
 	 * @private
 	 * @constructor
 	 * @param {Array} [entries] The key-value pairs to cache.
 	 */
@@ -9544,38 +9561,39 @@ var Debugger =
 	ListCache.prototype.get = listCacheGet;
 	ListCache.prototype.has = listCacheHas;
 	ListCache.prototype.set = listCacheSet;
 	
 	module.exports = ListCache;
 
 
 /***/ },
-/* 75 */
+/* 76 */
 /***/ 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;
 
 
 /***/ },
-/* 76 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assocIndexOf = __webpack_require__(77);
+/* 77 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assocIndexOf = __webpack_require__(78);
 	
 	/** Used for built-in method references. */
 	var arrayProto = Array.prototype;
 	
 	/** Built-in value references. */
 	var splice = arrayProto.splice;
 	
 	/**
@@ -9595,33 +9613,34 @@ var Debugger =
 	    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;
 
 
 /***/ },
-/* 77 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var eq = __webpack_require__(78);
+/* 78 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var eq = __webpack_require__(79);
 	
 	/**
 	 * Gets the index at which the `key` is found in `array` of key-value pairs.
 	 *
 	 * @private
-	 * @param {Array} array The array to search.
+	 * @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;
@@ -9629,35 +9648,35 @@ var Debugger =
 	  }
 	  return -1;
 	}
 	
 	module.exports = assocIndexOf;
 
 
 /***/ },
-/* 78 */
+/* 79 */
 /***/ function(module, exports) {
 
 	/**
 	 * Performs a
-	 * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+	 * [`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 = { 'user': 'fred' };
-	 * var other = { 'user': 'fred' };
+	 * var object = { 'a': 1 };
+	 * var other = { 'a': 1 };
 	 *
 	 * _.eq(object, object);
 	 * // => true
 	 *
 	 * _.eq(object, other);
 	 * // => false
 	 *
 	 * _.eq('a', 'a');
@@ -9672,20 +9691,20 @@ var Debugger =
 	function eq(value, other) {
 	  return value === other || (value !== value && other !== other);
 	}
 	
 	module.exports = eq;
 
 
 /***/ },
-/* 79 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assocIndexOf = __webpack_require__(77);
+/* 80 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assocIndexOf = __webpack_require__(78);
 	
 	/**
 	 * Gets the list cache value for `key`.
 	 *
 	 * @private
 	 * @name get
 	 * @memberOf ListCache
 	 * @param {string} key The key of the value to get.
@@ -9697,20 +9716,20 @@ var Debugger =
 	
 	  return index < 0 ? undefined : data[index][1];
 	}
 	
 	module.exports = listCacheGet;
 
 
 /***/ },
-/* 80 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assocIndexOf = __webpack_require__(77);
+/* 81 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assocIndexOf = __webpack_require__(78);
 	
 	/**
 	 * Checks if a list cache value for `key` exists.
 	 *
 	 * @private
 	 * @name has
 	 * @memberOf ListCache
 	 * @param {string} key The key of the entry to check.
@@ -9719,86 +9738,89 @@ var Debugger =
 	function listCacheHas(key) {
 	  return assocIndexOf(this.__data__, key) > -1;
 	}
 	
 	module.exports = listCacheHas;
 
 
 /***/ },
-/* 81 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assocIndexOf = __webpack_require__(77);
+/* 82 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assocIndexOf = __webpack_require__(78);
 	
 	/**
 	 * 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;
 
 
 /***/ },
-/* 82 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getNative = __webpack_require__(60),
-	    root = __webpack_require__(66);
+/* 83 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getNative = __webpack_require__(61),
+	    root = __webpack_require__(67);
 	
 	/* Built-in method references that are verified to be native. */
 	var Map = getNative(root, 'Map');
 	
 	module.exports = Map;
 
 
 /***/ },
-/* 83 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getMapData = __webpack_require__(84);
+/* 84 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getMapData = __webpack_require__(85);
 	
 	/**
 	 * 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) {
-	  return getMapData(this, key)['delete'](key);
+	  var result = getMapData(this, key)['delete'](key);
+	  this.size -= result ? 1 : 0;
+	  return result;
 	}
 	
 	module.exports = mapCacheDelete;
 
 
 /***/ },
-/* 84 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isKeyable = __webpack_require__(85);
+/* 85 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isKeyable = __webpack_require__(86);
 	
 	/**
 	 * Gets the data for `map`.
 	 *
 	 * @private
 	 * @param {Object} map The map to query.
 	 * @param {string} key The reference key.
 	 * @returns {*} Returns the map data.
@@ -9809,17 +9831,17 @@ var Debugger =
 	    ? data[typeof key == 'string' ? 'string' : 'hash']
 	    : data.map;
 	}
 	
 	module.exports = getMapData;
 
 
 /***/ },
-/* 85 */
+/* 86 */
 /***/ 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`.
@@ -9830,20 +9852,20 @@ var Debugger =
 	    ? (value !== '__proto__')
 	    : (value === null);
 	}
 	
 	module.exports = isKeyable;
 
 
 /***/ },
-/* 86 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getMapData = __webpack_require__(84);
+/* 87 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getMapData = __webpack_require__(85);
 	
 	/**
 	 * Gets the map value for `key`.
 	 *
 	 * @private
 	 * @name get
 	 * @memberOf MapCache
 	 * @param {string} key The key of the value to get.
@@ -9852,20 +9874,20 @@ var Debugger =
 	function mapCacheGet(key) {
 	  return getMapData(this, key).get(key);
 	}
 	
 	module.exports = mapCacheGet;
 
 
 /***/ },
-/* 87 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getMapData = __webpack_require__(84);
+/* 88 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getMapData = __webpack_require__(85);
 	
 	/**
 	 * Checks if a map value for `key` exists.
 	 *
 	 * @private
 	 * @name has
 	 * @memberOf MapCache
 	 * @param {string} key The key of the entry to check.
@@ -9874,55 +9896,59 @@ var Debugger =
 	function mapCacheHas(key) {
 	  return getMapData(this, key).has(key);
 	}
 	
 	module.exports = mapCacheHas;
 
 
 /***/ },
-/* 88 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getMapData = __webpack_require__(84);
+/* 89 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getMapData = __webpack_require__(85);
 	
 	/**
 	 * 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) {
-	  getMapData(this, key).set(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;
 
 
 /***/ },
-/* 89 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var baseToString = __webpack_require__(90);
+/* 90 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var baseToString = __webpack_require__(91);
 	
 	/**
 	 * 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 process.
-	 * @returns {string} Returns the string.
+	 * @param {*} value The value to convert.
+	 * @returns {string} Returns the converted string.
 	 * @example
 	 *
 	 * _.toString(null);
 	 * // => ''
 	 *
 	 * _.toString(-0);
 	 * // => '-0'
 	 *
@@ -9932,21 +9958,23 @@ var Debugger =
 	function toString(value) {
 	  return value == null ? '' : baseToString(value);
 	}
 	
 	module.exports = toString;
 
 
 /***/ },
-/* 90 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var Symbol = __webpack_require__(91),
-	    isSymbol = __webpack_require__(92);
+/* 91 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var Symbol = __webpack_require__(92),
+	    arrayMap = __webpack_require__(93),
+	    isArray = __webpack_require__(52),
+	    isSymbol = __webpack_require__(94);
 	
 	/** 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;
 	
@@ -9958,67 +9986,97 @@ var Debugger =
 	 * @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;
 
 
 /***/ },
-/* 91 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var root = __webpack_require__(66);
+/* 92 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var root = __webpack_require__(67);
 	
 	/** Built-in value references. */
 	var Symbol = root.Symbol;
 	
 	module.exports = Symbol;
 
 
 /***/ },
-/* 92 */
+/* 93 */
+/***/ 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 ? array.length : 0,
+	      result = Array(length);
+	
+	  while (++index < length) {
+	    result[index] = iteratee(array[index], index, array);
+	  }
+	  return result;
+	}
+	
+	module.exports = arrayMap;
+
+
+/***/ },
+/* 94 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var isObjectLike = __webpack_require__(7);
 	
 	/** `Object#toString` result references. */
 	var symbolTag = '[object Symbol]';
 	
 	/** Used for built-in method references. */
 	var objectProto = Object.prototype;
 	
 	/**
 	 * Used to resolve the
-	 * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+	 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 	 * of values.
 	 */
 	var objectToString = objectProto.toString;
 	
 	/**
 	 * 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 correctly classified,
-	 *  else `false`.
+	 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 	 * @example
 	 *
 	 * _.isSymbol(Symbol.iterator);
 	 * // => true
 	 *
 	 * _.isSymbol('abc');
 	 * // => false
 	 */
@@ -10026,21 +10084,21 @@ var Debugger =
 	  return typeof value == 'symbol' ||
 	    (isObjectLike(value) && objectToString.call(value) == symbolTag);
 	}
 	
 	module.exports = isSymbol;
 
 
 /***/ },
-/* 93 */
+/* 95 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var isArray = __webpack_require__(52),
-	    isSymbol = __webpack_require__(92);
+	    isSymbol = __webpack_require__(94);
 	
 	/** 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.
 	 *
@@ -10061,20 +10119,20 @@ var Debugger =
 	  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
 	    (object != null && value in Object(object));
 	}
 	
 	module.exports = isKey;
 
 
 /***/ },
-/* 94 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isSymbol = __webpack_require__(92);
+/* 96 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isSymbol = __webpack_require__(94);
 	
 	/** 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
@@ -10088,17 +10146,17 @@ var Debugger =
 	  var result = (value + '');
 	  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
 	}
 	
 	module.exports = toKey;
 
 
 /***/ },
-/* 95 */
+/* 97 */
 /***/ function(module, exports) {
 
 	function Debuggee() {
 	  function $(selector) {
 	    var element = document.querySelector(selector);
 	    console.log("$", selector, element);
 	
 	    if (!element) {
@@ -10218,25 +10276,25 @@ var Debugger =
 	  return window.client.debuggeeCommand(debuggeeStatement).then(result => {
 	    injectedDebuggee = result;
 	  });
 	}
 	
 	module.exports = injectDebuggee;
 
 /***/ },
-/* 96 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var _require = __webpack_require__(97);
+/* 98 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var _require = __webpack_require__(99);
 	
 	var Task = _require.Task;
 	
-	var firefox = __webpack_require__(98);
-	var chrome = __webpack_require__(173);
+	var firefox = __webpack_require__(100);
+	var chrome = __webpack_require__(176);
 	
 	var _require2 = __webpack_require__(45);
 	
 	var debugGlobal = _require2.debugGlobal;
 	
 	
 	var clientType = void 0;
 	function getClient() {
@@ -10284,17 +10342,17 @@ var Debugger =
 	
 	module.exports = {
 	  getClient,
 	  connectClients,
 	  startDebugging
 	};
 
 /***/ },
-/* 97 */
+/* 99 */
 /***/ function(module, exports) {
 
 	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
 	/* 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/. */
 	
@@ -10335,54 +10393,54 @@ var Debugger =
 	      callNext(undefined);
 	    });
 	  }
 	};
 	
 	module.exports = { Task };
 
 /***/ },
-/* 98 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var _require = __webpack_require__(99);
+/* 100 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var _require = __webpack_require__(101);
 	
 	var DebuggerClient = _require.DebuggerClient;
 	
-	var _require2 = __webpack_require__(105);
+	var _require2 = __webpack_require__(107);
 	
 	var DebuggerTransport = _require2.DebuggerTransport;
 	
-	var WebSocketDebuggerTransport = __webpack_require__(110);
-	
-	var _require3 = __webpack_require__(113);
+	var WebSocketDebuggerTransport = __webpack_require__(112);
+	
+	var _require3 = __webpack_require__(115);
 	
 	var TargetFactory = _require3.TargetFactory;
 	
-	var defer = __webpack_require__(112);
+	var defer = __webpack_require__(114);
 	
 	var _require4 = __webpack_require__(46);
 	
 	var getValue = _require4.getValue;
 	
-	var _require5 = __webpack_require__(114);
+	var _require5 = __webpack_require__(116);
 	
 	var Tab = _require5.Tab;
 	
-	var _require6 = __webpack_require__(170);
+	var _require6 = __webpack_require__(173);
 	
 	var setupCommands = _require6.setupCommands;
 	var clientCommands = _require6.clientCommands;
 	
-	var _require7 = __webpack_require__(171);
+	var _require7 = __webpack_require__(174);
 	
 	var setupEvents = _require7.setupEvents;
 	var clientEvents = _require7.clientEvents;
 	
-	var _require8 = __webpack_require__(172);
+	var _require8 = __webpack_require__(175);
 	
 	var createSource = _require8.createSource;
 	
 	
 	var debuggerClient = null;
 	var threadClient = null;
 	var tabTarget = null;
 	
@@ -10474,17 +10532,17 @@ var Debugger =
 	  });
 	
 	  // In Firefox, we need to initially request all of the sources. This
 	  // usually fires off individual `newSource` notifications as the
 	  // debugger finds them, but there may be existing sources already in
 	  // the debugger (if it's paused already, or if loading the page from
 	  // bfcache) so explicity fire `newSource` events for all returned
 	  // sources.
-	  return threadClient.getSources().then(_ref => {
+	  return threadClient.getSources().then((_ref) => {
 	    var sources = _ref.sources;
 	
 	    actions.newSources(sources.map(createSource));
 	
 	    // If the threadClient is already paused, make sure to show a
 	    // paused state.
 	    var pausedPacket = threadClient.getLastPausePacket();
 	    if (pausedPacket) {
@@ -10500,17 +10558,17 @@ var Debugger =
 	  getThreadClient,
 	  setThreadClient,
 	  getTabTarget,
 	  setTabTarget,
 	  initPage
 	};
 
 /***/ },
-/* 99 */
+/* 101 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
@@ -10519,18 +10577,18 @@ var Debugger =
 	const { Ci, Cu, components } = __webpack_require__(28);
 	const { Services } = __webpack_require__(33);
 	const DevToolsUtils = __webpack_require__(27);
 	
 	// WARNING I swapped the sync one for the async one here
 	//const promise = require("resource://devtools/shared/deprecated-sync-thenables.js", {}).Promise;
 	const promise = __webpack_require__(39);
 	
-	const events = __webpack_require__(100);
-	const { WebConsoleClient } = __webpack_require__(103);
+	const events = __webpack_require__(102);
+	const { WebConsoleClient } = __webpack_require__(105);
 	/*const { DebuggerSocket } = require("devtools-sham/shared/security/socket");*/
 	/*const Authentication = require("devtools-sham/shared/security/auth");*/
 	
 	const noop = () => {};
 	
 	/**
 	 * TODO: Get rid of this API in favor of EventTarget (bug 1042642)
 	 *
@@ -13667,32 +13725,32 @@ var Debugger =
 	    telemetry: "ASSIGN"
 	  })
 	};
 	
 	eventSource(EnvironmentClient.prototype);
 
 
 /***/ },
-/* 100 */
+/* 102 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* WEBPACK VAR INJECTION */(function(module) {/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	"use strict";
 	
 	module.metadata = {
 	  "stability": "unstable"
 	};
 	
 	const UNCAUGHT_ERROR = 'An error event was emitted for which there was no listener.';
 	const BAD_LISTENER = 'The event listener must be a function.';
 	
-	const { ns } = __webpack_require__(102);
+	const { ns } = __webpack_require__(104);
 	
 	const event = ns();
 	
 	const EVENT_TYPE_PATTERN = /^on([A-Z]\w+$)/;
 	exports.EVENT_TYPE_PATTERN = EVENT_TYPE_PATTERN;
 	
 	// Utility function to access given event `target` object's event listeners for
 	// the specific event `type`. If listeners for this type does not exists they
@@ -13864,36 +13922,36 @@ var Debugger =
 	
 	    let listener = listeners[key];
 	    if (typeof(listener) === 'function')
 	      on(target, type, listener);
 	  });
 	}
 	exports.setListeners = setListeners;
 	
-	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(101)(module)))
-
-/***/ },
-/* 101 */
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(103)(module)))
+
+/***/ },
+/* 103 */
 /***/ function(module, exports) {
 
 	module.exports = function(module) {
 		if(!module.webpackPolyfill) {
 			module.deprecate = function() {};
 			module.paths = [];
 			// module.parent = undefined by default
 			module.children = [];
 			module.webpackPolyfill = 1;
 		}
 		return module;
 	}
 
 
 /***/ },
-/* 102 */
+/* 104 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* WEBPACK VAR INJECTION */(function(module) {/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
@@ -13930,35 +13988,35 @@ var Debugger =
 	  };
 	};
 	
 	// `Namespace` is a e4x function in the scope, so we export the function also as
 	// `ns` as alias to avoid clashing.
 	exports.ns = ns;
 	exports.Namespace = ns;
 	
-	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(101)(module)))
-
-/***/ },
-/* 103 */
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(103)(module)))
+
+/***/ },
+/* 105 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
 	/* vim: set ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	const {Cc, Ci, Cu} = __webpack_require__(28);
 	const DevToolsUtils = __webpack_require__(27);
-	const EventEmitter = __webpack_require__(104);
+	const EventEmitter = __webpack_require__(106);
 	const promise = __webpack_require__(39);
-	const {LongStringClient} = __webpack_require__(99);
+	const {LongStringClient} = __webpack_require__(101);
 	
 	/**
 	 * A WebConsoleClient is used as a front end for the WebConsoleActor that is
 	 * created on the server, hiding implementation details.
 	 *
 	 * @param object aDebuggerClient
 	 *        The DebuggerClient instance we live for.
 	 * @param object aResponse
@@ -14606,17 +14664,17 @@ var Debugger =
 	    });
 	
 	    return deferred.promise;
 	  }
 	};
 
 
 /***/ },
-/* 104 */
+/* 106 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* 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/. */
 	
 	/**
 	 * EventEmitter.
@@ -14744,39 +14802,39 @@ var Debugger =
 	        }
 	      }
 	    }
 	  },
 	};
 
 
 /***/ },
-/* 105 */
+/* 107 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* eslint-env browser */
 	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	// TODO: Get rid of this code once the marionette server loads transport.js as
 	// an SDK module (see bug 1000814)
 	
 	"use strict";
 	
 	const DevToolsUtils = __webpack_require__(27);
 	const { dumpn, dumpv } = DevToolsUtils;
-	const StreamUtils = __webpack_require__(106);
+	const StreamUtils = __webpack_require__(108);
 	const { Packet, JSONPacket, BulkPacket } =
-	  __webpack_require__(107);
+	  __webpack_require__(109);
 	const promise = __webpack_require__(39);
-	const EventEmitter = __webpack_require__(104);
-	const utf8 = __webpack_require__(109);
+	const EventEmitter = __webpack_require__(106);
+	const utf8 = __webpack_require__(111);
 	
 	const PACKET_HEADER_MAX = 200;
 	
 	/**
 	 * An adapter that handles data transfers between the debugger client and
 	 * server. It can work with both nsIPipe and nsIServerSocket transports so
 	 * long as the properly created input and output streams are specified.
 	 * (However, for intra-process connections, LocalDebuggerTransport, below,
@@ -15616,30 +15674,30 @@ var Debugger =
 	    };
 	
 	    exports.WorkerDebuggerTransport = WorkerDebuggerTransport;
 	  }).call(this);
 	}
 
 
 /***/ },
-/* 106 */
+/* 108 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	const { Ci, Cc, Cu, Cr, CC } = __webpack_require__(28);
 	const Services = __webpack_require__(33);
 	const DevToolsUtils = __webpack_require__(27);
 	const { dumpv } = DevToolsUtils;
-	const EventEmitter = __webpack_require__(104);
+	const EventEmitter = __webpack_require__(106);
 	const promise = __webpack_require__(39);
 	
 	const IOUtil = Cc("@mozilla.org/io-util;1").getService(Ci.nsIIOUtil);
 	
 	const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
 	          "nsIScriptableInputStream", "init");
 	
 	const BUFFER_SIZE = 0x8000;
@@ -15866,17 +15924,17 @@ var Debugger =
 	
 	module.exports = {
 	  copyStream: copyStream,
 	  delimitedRead: delimitedRead
 	};
 
 
 /***/ },
-/* 107 */
+/* 109 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
@@ -15898,26 +15956,26 @@ var Debugger =
 	 *     Returns true once the packet is done being read / written
 	 *   * destroy()
 	 *     Called to clean up at the end of use
 	 */
 	
 	const { Cc, Ci, Cu } = __webpack_require__(28);
 	const DevToolsUtils = __webpack_require__(27);
 	const { dumpn, dumpv } = DevToolsUtils;
-	const StreamUtils = __webpack_require__(106);
+	const StreamUtils = __webpack_require__(108);
 	const promise = __webpack_require__(39);
 	
 	/*DevToolsUtils.defineLazyGetter(this, "unicodeConverter", () => {
 	  const unicodeConverter = Cc("@mozilla.org/intl/scriptableunicodeconverter")
 	                           .createInstance(Ci.nsIScriptableUnicodeConverter);
 	  unicodeConverter.charset = "UTF-8";
 	  return unicodeConverter;
 	});*/
-	const utf8 = __webpack_require__(108);
+	const utf8 = __webpack_require__(110);
 	
 	// The transport's previous check ensured the header length did not exceed 20
 	// characters.  Here, we opt for the somewhat smaller, but still large limit of
 	// 1 TiB.
 	const PACKET_LENGTH_MAX = Math.pow(2, 40);
 	
 	/**
 	 * A generic Packet processing object (extended by two subtypes below).
@@ -16290,17 +16348,17 @@ var Debugger =
 	Object.defineProperty(RawPacket.prototype, "done", {
 	  get: function() { return this._done; }
 	});
 	
 	exports.RawPacket = RawPacket;
 
 
 /***/ },
-/* 108 */
+/* 110 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/utf8js v2.0.0 by @mathias */
 	;(function(root) {
 	
 		// Detect free variables `exports`
 		var freeExports = typeof exports == 'object' && exports;
 	
@@ -16536,20 +16594,20 @@ var Debugger =
 				}
 			}
 		} else { // in Rhino or a web browser
 			root.utf8 = utf8;
 		}
 	
 	}(this));
 	
-	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(101)(module), (function() { return this; }())))
-
-/***/ },
-/* 109 */
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(103)(module), (function() { return this; }())))
+
+/***/ },
+/* 111 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/utf8js v2.0.0 by @mathias */
 	;(function(root) {
 	
 		// Detect free variables `exports`
 		var freeExports = typeof exports == 'object' && exports;
 	
@@ -16785,29 +16843,29 @@ var Debugger =
 				}
 			}
 		} else { // in Rhino or a web browser
 			root.utf8 = utf8;
 		}
 	
 	}(this));
 	
-	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(101)(module), (function() { return this; }())))
-
-/***/ },
-/* 110 */
-/***/ function(module, exports, __webpack_require__) {
-
-	/* This Source Code Form is subject to the terms of the Mozilla Public
-	 * License, v. 2.0. If a copy of the MPL was not distributed with this
-	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-	
-	"use strict";
-	
-	const EventEmitter = __webpack_require__(111);
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(103)(module), (function() { return this; }())))
+
+/***/ },
+/* 112 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* This Source Code Form is subject to the terms of the Mozilla Public
+	 * License, v. 2.0. If a copy of the MPL was not distributed with this
+	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+	
+	"use strict";
+	
+	const EventEmitter = __webpack_require__(113);
 	
 	function WebSocketDebuggerTransport(socket) {
 	  EventEmitter.decorate(this);
 	
 	  this.active = false;
 	  this.hooks = null;
 	  this.socket = socket;
 	}
@@ -16873,22 +16931,22 @@ var Debugger =
 	    }
 	  },
 	};
 	
 	module.exports = WebSocketDebuggerTransport;
 
 
 /***/ },
-/* 111 */
+/* 113 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var EventEmitter = function () {};
 	
-	var defer = __webpack_require__(112);
+	var defer = __webpack_require__(114);
 	
 	/**
 	 * Decorate an object with event emitter functionality.
 	 *
 	 * @param Object objectToDecorate
 	 *        Bind all public methods of EventEmitter to
 	 *        the objectToDecorate object.
 	 */
@@ -17017,17 +17075,17 @@ var Debugger =
 	      if (_ret === "break") break;
 	    }
 	  }
 	};
 	
 	module.exports = EventEmitter;
 
 /***/ },
-/* 112 */
+/* 114 */
 /***/ function(module, exports) {
 
 	module.exports = function defer() {
 	  var resolve = void 0,
 	      reject = void 0;
 	  var promise = new Promise(function () {
 	    resolve = arguments[0];
 	    reject = arguments[1];
@@ -17035,32 +17093,32 @@ var Debugger =
 	  return {
 	    resolve: resolve,
 	    reject: reject,
 	    promise: promise
 	  };
 	};
 
 /***/ },
-/* 113 */
+/* 115 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
 	"use strict";
 	
 	const { Ci, Cu } = __webpack_require__(28);
 	const promise = __webpack_require__(39);
-	const EventEmitter = __webpack_require__(104);
+	const EventEmitter = __webpack_require__(106);
 	const { Services } = __webpack_require__(33);
 	
 	/*const { DebuggerServer } = require("devtools-sham/server/main");*/
-	const { DebuggerClient } = __webpack_require__(99);
+	const { DebuggerClient } = __webpack_require__(101);
 	
 	const targets = new WeakMap();
 	const promiseTargets = new WeakMap();
 	
 	/**
 	 * Functions for creating Targets
 	 */
 	exports.TargetFactory = {
@@ -17731,20 +17789,20 @@ var Debugger =
 	
 	  makeRemote: function () {
 	    return Promise.resolve();
 	  }
 	};
 
 
 /***/ },
-/* 114 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var t = __webpack_require__(115);
+/* 116 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var t = __webpack_require__(117);
 	
 	var Tab = t.struct({
 	  title: t.String,
 	  url: t.String,
 	  id: t.String,
 	  tab: t.Object,
 	  browser: t.enums.of(["chrome", "firefox"])
 	}, "Tab");
@@ -17794,97 +17852,97 @@ var Debugger =
 	  SourceText,
 	  Location,
 	  Breakpoint,
 	  BreakpointResult,
 	  Frame
 	};
 
 /***/ },
-/* 115 */
+/* 117 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/*! @preserve
 	 *
 	 * tcomb.js - Type checking and DDD for JavaScript
 	 *
 	 * The MIT License (MIT)
 	 *
 	 * Copyright (c) 2014-2016 Giulio Canti
 	 *
 	 */
 	
 	// core
-	var t = __webpack_require__(116);
+	var t = __webpack_require__(118);
 	
 	// types
-	t.Any = __webpack_require__(122);
-	t.Array = __webpack_require__(130);
-	t.Boolean = __webpack_require__(131);
-	t.Date = __webpack_require__(133);
-	t.Error = __webpack_require__(134);
-	t.Function = __webpack_require__(135);
-	t.Nil = __webpack_require__(136);
-	t.Number = __webpack_require__(137);
-	t.Integer = __webpack_require__(139);
+	t.Any = __webpack_require__(124);
+	t.Array = __webpack_require__(132);
+	t.Boolean = __webpack_require__(133);
+	t.Date = __webpack_require__(135);
+	t.Error = __webpack_require__(136);
+	t.Function = __webpack_require__(137);
+	t.Nil = __webpack_require__(138);
+	t.Number = __webpack_require__(139);
+	t.Integer = __webpack_require__(141);
 	t.IntegerT = t.Integer;
-	t.Object = __webpack_require__(145);
-	t.RegExp = __webpack_require__(146);
-	t.String = __webpack_require__(147);
-	t.Type = __webpack_require__(148);
+	t.Object = __webpack_require__(147);
+	t.RegExp = __webpack_require__(148);
+	t.String = __webpack_require__(149);
+	t.Type = __webpack_require__(150);
 	t.TypeT = t.Type;
 	
 	// short alias are deprecated
 	t.Arr = t.Array;
 	t.Bool = t.Boolean;
 	t.Dat = t.Date;
 	t.Err = t.Error;
 	t.Func = t.Function;
 	t.Num = t.Number;
 	t.Obj = t.Object;
 	t.Re = t.RegExp;
 	t.Str = t.String;
 	
 	// combinators
-	t.dict = __webpack_require__(149);
-	t.declare = __webpack_require__(150);
-	t.enums = __webpack_require__(152);
-	t.irreducible = __webpack_require__(123);
-	t.list = __webpack_require__(153);
-	t.maybe = __webpack_require__(154);
-	t.refinement = __webpack_require__(140);
-	t.struct = __webpack_require__(156);
-	t.tuple = __webpack_require__(162);
-	t.union = __webpack_require__(163);
-	t.func = __webpack_require__(165);
-	t.intersection = __webpack_require__(166);
+	t.dict = __webpack_require__(151);
+	t.declare = __webpack_require__(152);
+	t.enums = __webpack_require__(155);
+	t.irreducible = __webpack_require__(125);
+	t.list = __webpack_require__(156);
+	t.maybe = __webpack_require__(157);
+	t.refinement = __webpack_require__(142);
+	t.struct = __webpack_require__(159);
+	t.tuple = __webpack_require__(165);
+	t.union = __webpack_require__(166);
+	t.func = __webpack_require__(167);
+	t.intersection = __webpack_require__(168);
 	t.subtype = t.refinement;
-	t.inter = __webpack_require__(167); // IE8 alias
+	t.inter = __webpack_require__(169); // IE8 alias
 	t['interface'] = t.inter;
 	
 	// functions
 	t.assert = t;
-	t.update = __webpack_require__(168);
-	t.mixin = __webpack_require__(151);
-	t.isType = __webpack_require__(127);
-	t.is = __webpack_require__(144);
-	t.getTypeName = __webpack_require__(126);
-	t.match = __webpack_require__(169);
+	t.update = __webpack_require__(171);
+	t.mixin = __webpack_require__(153);
+	t.isType = __webpack_require__(129);
+	t.is = __webpack_require__(146);
+	t.getTypeName = __webpack_require__(128);
+	t.match = __webpack_require__(172);
 	
 	module.exports = t;
 
 
 /***/ },
-/* 116 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isFunction = __webpack_require__(117);
-	var isNil = __webpack_require__(118);
-	var fail = __webpack_require__(119);
-	var stringify = __webpack_require__(120);
+/* 118 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isFunction = __webpack_require__(119);
+	var isNil = __webpack_require__(120);
+	var fail = __webpack_require__(121);
+	var stringify = __webpack_require__(122);
 	
 	function assert(guard, message) {
 	  if (guard !== true) {
 	    if (isFunction(message)) { // handle lazy messages
 	      message = message();
 	    }
 	    else if (isNil(message)) { // use a default message
 	      message = 'Assert failed (turn on "Pause on exceptions" in your Source panel)';
@@ -17894,44 +17952,44 @@ var Debugger =
 	}
 	
 	assert.fail = fail;
 	assert.stringify = stringify;
 	
 	module.exports = assert;
 
 /***/ },
-/* 117 */
+/* 119 */
 /***/ function(module, exports) {
 
 	module.exports = function isFunction(x) {
 	  return typeof x === 'function';
 	};
 
 /***/ },
-/* 118 */
+/* 120 */
 /***/ function(module, exports) {
 
 	module.exports = function isNil(x) {
 	  return x === null || x === void 0;
 	};
 
 /***/ },
-/* 119 */
+/* 121 */
 /***/ function(module, exports) {
 
 	module.exports = function fail(message) {
 	  throw new TypeError('[tcomb] ' + message);
 	};
 
 /***/ },
-/* 120 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getFunctionName = __webpack_require__(121);
+/* 122 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getFunctionName = __webpack_require__(123);
 	
 	function replacer(key, value) {
 	  if (typeof value === 'function') {
 	    return getFunctionName(value);
 	  }
 	  return value;
 	}
 	
@@ -17940,40 +17998,40 @@ var Debugger =
 	    return JSON.stringify(x, replacer, 2);
 	  }
 	  catch (e) {
 	    return String(x);
 	  }
 	};
 
 /***/ },
-/* 121 */
+/* 123 */
 /***/ function(module, exports) {
 
 	module.exports = function getFunctionName(f) {
 	  return f.displayName || f.name || '<function' + f.length + '>';
 	};
 
 /***/ },
-/* 122 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var irreducible = __webpack_require__(123);
+/* 124 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var irreducible = __webpack_require__(125);
 	
 	module.exports = irreducible('Any', function () { return true; });
 
 
 /***/ },
-/* 123 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var isString = __webpack_require__(124);
-	var isFunction = __webpack_require__(117);
-	var forbidNewOperator = __webpack_require__(125);
+/* 125 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var isString = __webpack_require__(126);
+	var isFunction = __webpack_require__(119);
+	var forbidNewOperator = __webpack_require__(127);
 	
 	module.exports = function irreducible(name, predicate) {
 	
 	  if (false) {
 	    assert(isString(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to irreducible(name, predicate) (expected a string)'; });
 	    assert(isFunction(predicate), 'Invalid argument predicate ' + assert.stringify(predicate) + ' supplied to irreducible(name, predicate) (expected a function)');
 	  }
 	
@@ -17999,185 +18057,185 @@ var Debugger =
 	
 	  Irreducible.is = predicate;
 	
 	  return Irreducible;
 	};
 
 
 /***/ },
-/* 124 */
+/* 126 */
 /***/ function(module, exports) {
 
 	module.exports = function isString(x) {
 	  return typeof x === 'string';
 	};
 
 /***/ },
-/* 125 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var getTypeName = __webpack_require__(126);
+/* 127 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var getTypeName = __webpack_require__(128);
 	
 	module.exports = function forbidNewOperator(x, type) {
 	  assert(!(x instanceof type), function () { return 'Cannot use the new operator to instantiate the type ' + getTypeName(type); });
 	};
 
 /***/ },
-/* 126 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isType = __webpack_require__(127);
-	var getFunctionName = __webpack_require__(121);
-	
-	module.exports = function getTypeName(constructor) {
-	  if (isType(constructor)) {
-	    return constructor.displayName;
-	  }
-	  return getFunctionName(constructor);
-	};
-
-/***/ },
-/* 127 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isFunction = __webpack_require__(117);
-	var isObject = __webpack_require__(128);
-	
-	module.exports = function isType(x) {
-	  return isFunction(x) && isObject(x.meta);
-	};
-
-/***/ },
 /* 128 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var isNil = __webpack_require__(118);
-	var isArray = __webpack_require__(129);
-	
-	module.exports = function isObject(x) {
-	  return !isNil(x) && typeof x === 'object' && !isArray(x);
+	var isType = __webpack_require__(129);
+	var getFunctionName = __webpack_require__(123);
+	
+	module.exports = function getTypeName(ctor) {
+	  if (isType(ctor)) {
+	    return ctor.displayName;
+	  }
+	  return getFunctionName(ctor);
 	};
 
 /***/ },
 /* 129 */
-/***/ function(module, exports) {
-
-	module.exports = function isArray(x) {
-	  return x instanceof Array;
+/***/ function(module, exports, __webpack_require__) {
+
+	var isFunction = __webpack_require__(119);
+	var isObject = __webpack_require__(130);
+	
+	module.exports = function isType(x) {
+	  return isFunction(x) && isObject(x.meta);
 	};
 
 /***/ },
 /* 130 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var irreducible = __webpack_require__(123);
-	var isArray = __webpack_require__(129);
-	
-	module.exports = irreducible('Array', isArray);
-
+	var isNil = __webpack_require__(120);
+	var isArray = __webpack_require__(131);
+	
+	module.exports = function isObject(x) {
+	  return !isNil(x) && typeof x === 'object' && !isArray(x);
+	};
 
 /***/ },
 /* 131 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var irreducible = __webpack_require__(123);
-	var isBoolean = __webpack_require__(132);
-	
-	module.exports = irreducible('Boolean', isBoolean);
-
+/***/ function(module, exports) {
+
+	module.exports = function isArray(x) {
+	  return Array.isArray ? Array.isArray(x) : x instanceof Array;
+	};
 
 /***/ },
 /* 132 */
-/***/ function(module, exports) {
-
-	module.exports = function isBoolean(x) {
-	  return x === true || x === false;
-	};
+/***/ function(module, exports, __webpack_require__) {
+
+	var irreducible = __webpack_require__(125);
+	var isArray = __webpack_require__(131);
+	
+	module.exports = irreducible('Array', isArray);
+
 
 /***/ },
 /* 133 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var irreducible = __webpack_require__(123);
-	
-	module.exports = irreducible('Date', function (x) { return x instanceof Date; });
+	var irreducible = __webpack_require__(125);
+	var isBoolean = __webpack_require__(134);
+	
+	module.exports = irreducible('Boolean', isBoolean);
 
 
 /***/ },
 /* 134 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var irreducible = __webpack_require__(123);
-	
-	module.exports = irreducible('Error', function (x) { return x instanceof Error; });
-
+/***/ function(module, exports) {
+
+	module.exports = function isBoolean(x) {
+	  return x === true || x === false;
+	};
 
 /***/ },
 /* 135 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var irreducible = __webpack_require__(123);
-	var isFunction = __webpack_require__(117);
-	
-	module.exports = irreducible('Function', isFunction);
+	var irreducible = __webpack_require__(125);
+	
+	module.exports = irreducible('Date', function (x) { return x instanceof Date; });
 
 
 /***/ },
 /* 136 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var irreducible = __webpack_require__(123);
-	var isNil = __webpack_require__(118);
-	
-	module.exports = irreducible('Nil', isNil);
+	var irreducible = __webpack_require__(125);
+	
+	module.exports = irreducible('Error', function (x) { return x instanceof Error; });
 
 
 /***/ },
 /* 137 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var irreducible = __webpack_require__(123);
-	var isNumber = __webpack_require__(138);
-	
-	module.exports = irreducible('Number', isNumber);
+	var irreducible = __webpack_require__(125);
+	var isFunction = __webpack_require__(119);
+	
+	module.exports = irreducible('Function', isFunction);
 
 
 /***/ },
 /* 138 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var irreducible = __webpack_require__(125);
+	var isNil = __webpack_require__(120);
+	
+	module.exports = irreducible('Nil', isNil);
+
+
+/***/ },
+/* 139 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var irreducible = __webpack_require__(125);
+	var isNumber = __webpack_require__(140);
+	
+	module.exports = irreducible('Number', isNumber);
+
+
+/***/ },
+/* 140 */
 /***/ function(module, exports) {
 
 	module.exports = function isNumber(x) {
 	  return typeof x === 'number' && isFinite(x) && !isNaN(x);
 	};
 
 /***/ },
-/* 139 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var refinement = __webpack_require__(140);
-	var Number = __webpack_require__(137);
+/* 141 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var refinement = __webpack_require__(142);
+	var Number = __webpack_require__(139);
 	
 	module.exports = refinement(Number, function (x) { return x % 1 === 0; }, 'Integer');
 
 
 /***/ },
-/* 140 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var isTypeName = __webpack_require__(141);
-	var isFunction = __webpack_require__(117);
-	var forbidNewOperator = __webpack_require__(125);
-	var isIdentity = __webpack_require__(142);
-	var create = __webpack_require__(143);
-	var is = __webpack_require__(144);
-	var getTypeName = __webpack_require__(126);
-	var getFunctionName = __webpack_require__(121);
+/* 142 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var isTypeName = __webpack_require__(143);
+	var isFunction = __webpack_require__(119);
+	var forbidNewOperator = __webpack_require__(127);
+	var isIdentity = __webpack_require__(144);
+	var create = __webpack_require__(145);
+	var is = __webpack_require__(146);
+	var getTypeName = __webpack_require__(128);
+	var getFunctionName = __webpack_require__(123);
 	
 	function getDefaultName(type, predicate) {
 	  return '{' + getTypeName(type) + ' | ' + getFunctionName(predicate) + '}';
 	}
 	
 	function refinement(type, predicate, name) {
 	
 	  if (false) {
@@ -18187,17 +18245,19 @@ var Debugger =
 	  }
 	
 	  var displayName = name || getDefaultName(type, predicate);
 	  var identity = isIdentity(type);
 	
 	  function Refinement(value, path) {
 	
 	    if (false) {
-	      forbidNewOperator(this, Refinement);
+	      if (identity) {
+	        forbidNewOperator(this, Refinement);
+	      }
 	      path = path || [displayName];
 	    }
 	
 	    var x = create(type, value, path);
 	
 	    if (false) {
 	      assert(predicate(x), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/'); });
 	    }
@@ -18226,137 +18286,136 @@ var Debugger =
 	  return Refinement;
 	}
 	
 	refinement.getDefaultName = getDefaultName;
 	module.exports = refinement;
 
 
 /***/ },
-/* 141 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isNil = __webpack_require__(118);
-	var isString = __webpack_require__(124);
+/* 143 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isNil = __webpack_require__(120);
+	var isString = __webpack_require__(126);
 	
 	module.exports = function isTypeName(name) {
 	  return isNil(name) || isString(name);
 	};
 
 /***/ },
-/* 142 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var Boolean = __webpack_require__(131);
-	var isType = __webpack_require__(127);
-	var getTypeName = __webpack_require__(126);
+/* 144 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var Boolean = __webpack_require__(133);
+	var isType = __webpack_require__(129);
+	var getTypeName = __webpack_require__(128);
 	
 	// return true if the type constructor behaves like the identity function
 	module.exports = function isIdentity(type) {
 	  if (isType(type)) {
 	    if (false) {
 	      assert(Boolean.is(type.meta.identity), function () { return 'Invalid meta identity ' + assert.stringify(type.meta.identity) + ' supplied to type ' + getTypeName(type); });
 	    }
 	    return type.meta.identity;
 	  }
 	  // for tcomb the other constructors, like ES6 classes, are identity-like
 	  return true;
 	};
 
 /***/ },
-/* 143 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isType = __webpack_require__(127);
-	var getFunctionName = __webpack_require__(121);
-	var assert = __webpack_require__(116);
-	var stringify = __webpack_require__(120);
+/* 145 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isType = __webpack_require__(129);
+	var getFunctionName = __webpack_require__(123);
+	var assert = __webpack_require__(118);
+	var stringify = __webpack_require__(122);
 	
 	// creates an instance of a type, handling the optional new operator
 	module.exports = function create(type, value, path) {
 	  if (isType(type)) {
-	    // for structs the new operator is allowed
-	    return type.meta.kind === 'struct' ? new type(value, path) : type(value, path);
+	    return !type.meta.identity && typeof value === 'object' && value !== null ? new type(value, path): type(value, path);
 	  }
 	
 	  if (false) {
 	    // here type should be a class constructor and value some instance, just check membership and return the value
 	    path = path || [getFunctionName(type)];
 	    assert(value instanceof type, function () { return 'Invalid value ' + stringify(value) + ' supplied to ' + path.join('/'); });
 	  }
 	
 	  return value;
 	};
 
 /***/ },
-/* 144 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isType = __webpack_require__(127);
+/* 146 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isType = __webpack_require__(129);
 	
 	// returns true if x is an instance of type
 	module.exports = function is(x, type) {
 	  if (isType(type)) {
 	    return type.is(x);
 	  }
 	  return x instanceof type; // type should be a class constructor
 	};
 
 
 /***/ },
-/* 145 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var irreducible = __webpack_require__(123);
-	var isObject = __webpack_require__(128);
+/* 147 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var irreducible = __webpack_require__(125);
+	var isObject = __webpack_require__(130);
 	
 	module.exports = irreducible('Object', isObject);
 
 
 /***/ },
-/* 146 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var irreducible = __webpack_require__(123);
-	
-	module.exports = irreducible('RegExp', function (x) { return x instanceof RegExp; });
-
-
-/***/ },
-/* 147 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var irreducible = __webpack_require__(123);
-	var isString = __webpack_require__(124);
-	
-	module.exports = irreducible('String', isString);
-
-
-/***/ },
 /* 148 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var irreducible = __webpack_require__(123);
-	var isType = __webpack_require__(127);
-	
-	module.exports = irreducible('Type', isType);
+	var irreducible = __webpack_require__(125);
+	
+	module.exports = irreducible('RegExp', function (x) { return x instanceof RegExp; });
+
 
 /***/ },
 /* 149 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var assert = __webpack_require__(116);
-	var isTypeName = __webpack_require__(141);
-	var isFunction = __webpack_require__(117);
-	var getTypeName = __webpack_require__(126);
-	var isIdentity = __webpack_require__(142);
-	var isObject = __webpack_require__(128);
-	var create = __webpack_require__(143);
-	var is = __webpack_require__(144);
+	var irreducible = __webpack_require__(125);
+	var isString = __webpack_require__(126);
+	
+	module.exports = irreducible('String', isString);
+
+
+/***/ },
+/* 150 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var irreducible = __webpack_require__(125);
+	var isType = __webpack_require__(129);
+	
+	module.exports = irreducible('Type', isType);
+
+/***/ },
+/* 151 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var isTypeName = __webpack_require__(143);
+	var isFunction = __webpack_require__(119);
+	var getTypeName = __webpack_require__(128);
+	var isIdentity = __webpack_require__(144);
+	var isObject = __webpack_require__(130);
+	var create = __webpack_require__(145);
+	var is = __webpack_require__(146);
 	
 	function getDefaultName(domain, codomain) {
 	  return '{[key: ' + getTypeName(domain) + ']: ' + getTypeName(codomain) + '}';
 	}
 	
 	function dict(domain, codomain, name) {
 	
 	  if (false) {
@@ -18437,77 +18496,83 @@ var Debugger =
 	  return Dict;
 	}
 	
 	dict.getDefaultName = getDefaultName;
 	module.exports = dict;
 
 
 /***/ },
-/* 150 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var isTypeName = __webpack_require__(141);
-	var isType = __webpack_require__(127);
-	var isNil = __webpack_require__(118);
-	var mixin = __webpack_require__(151);
-	var getTypeName = __webpack_require__(126);
+/* 152 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var isTypeName = __webpack_require__(143);
+	var isType = __webpack_require__(129);
+	var isNil = __webpack_require__(120);
+	var mixin = __webpack_require__(153);
+	var getTypeName = __webpack_require__(128);
+	var isUnion = __webpack_require__(154);
 	
 	// All the .declare-d types should be clearly different from each other thus they should have
 	// different names when a name was not explicitly provided.
 	var nextDeclareUniqueId = 1;
 	
 	module.exports = function declare(name) {
 	  if (false) {
 	    assert(isTypeName(name), function () { return 'Invalid argument name ' + name + ' supplied to declare([name]) (expected a string)'; });
 	  }
 	
 	  var type;
 	
 	  function Declare(value, path) {
 	    if (false) {
 	      assert(!isNil(type), function () { return 'Type declared but not defined, don\'t forget to call .define on every declared type'; });
+	      if (isUnion(type)) {
+	        assert(type.dispatch === Declare.dispatch, function () { return 'Please define the custom ' + name + '.dispatch function before calling ' + name + '.define()'; });
+	      }
 	    }
 	    return type(value, path);
 	  }
 	
 	  Declare.define = function (spec) {
 	    if (false) {
 	      assert(isType(spec), function () { return 'Invalid argument type ' + assert.stringify(spec) +  ' supplied to define(type) (expected a type)'; });
 	      assert(isNil(type), function () { return 'Declare.define(type) can only be invoked once'; });
 	      assert(isNil(spec.meta.name) && Object.keys(spec.prototype).length === 0, function () { return 'Invalid argument type ' + assert.stringify(spec) + ' supplied to define(type) (expected a fresh, unnamed type)'; });
 	    }
 	
+	    if (isUnion(spec) && Declare.hasOwnProperty('dispatch')) {
+	      spec.dispatch = Declare.dispatch;
+	    }
 	    type = spec;
 	    mixin(Declare, type, true); // true because it overwrites Declare.displayName
 	    if (name) {
 	      type.displayName = Declare.displayName = name;
 	      Declare.meta.name = name;
 	    }
-	    // ensure identity is still false
-	    Declare.meta.identity = false;
+	    Declare.meta.identity = type.meta.identity;
 	    Declare.prototype = type.prototype;
 	    return Declare;
 	  };
 	
 	  Declare.displayName = name || ( getTypeName(Declare) + "$" + nextDeclareUniqueId++ );
 	  // in general I can't say if this type will be an identity, for safety setting to false
 	  Declare.meta = { identity: false };
 	  Declare.prototype = null;
 	  return Declare;
 	};
 
 
 /***/ },
-/* 151 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isNil = __webpack_require__(118);
-	var assert = __webpack_require__(116);
+/* 153 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isNil = __webpack_require__(120);
+	var assert = __webpack_require__(118);
 	
 	// safe mixin, cannot override props unless specified
 	module.exports = function mixin(target, source, overwrite) {
 	  if (isNil(source)) { return target; }
 	  for (var k in source) {
 	    if (source.hasOwnProperty(k)) {
 	      if (overwrite !== true) {
 	        if (false) {
@@ -18516,24 +18581,34 @@ var Debugger =
 	      }
 	      target[k] = source[k];
 	    }
 	  }
 	  return target;
 	};
 
 /***/ },
-/* 152 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var isTypeName = __webpack_require__(141);
-	var forbidNewOperator = __webpack_require__(125);
-	var isString = __webpack_require__(124);
-	var isObject = __webpack_require__(128);
+/* 154 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isType = __webpack_require__(129);
+	
+	module.exports = function isUnion(x) {
+	  return isType(x) && ( x.meta.kind === 'union' );
+	};
+
+/***/ },
+/* 155 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var isTypeName = __webpack_require__(143);
+	var forbidNewOperator = __webpack_require__(127);
+	var isString = __webpack_require__(126);
+	var isObject = __webpack_require__(130);
 	
 	function getDefaultName(map) {
 	  return Object.keys(map).map(function (k) { return assert.stringify(k); }).join(' | ');
 	}
 	
 	function enums(map, name) {
 	
 	  if (false) {
@@ -18580,27 +18655,27 @@ var Debugger =
 	};
 	
 	enums.getDefaultName = getDefaultName;
 	module.exports = enums;
 	
 
 
 /***/ },
-/* 153 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var isTypeName = __webpack_require__(141);
-	var isFunction = __webpack_require__(117);
-	var getTypeName = __webpack_require__(126);
-	var isIdentity = __webpack_require__(142);
-	var create = __webpack_require__(143);
-	var is = __webpack_require__(144);
-	var isArray = __webpack_require__(129);
+/* 156 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var isTypeName = __webpack_require__(143);
+	var isFunction = __webpack_require__(119);
+	var getTypeName = __webpack_require__(128);
+	var isIdentity = __webpack_require__(144);
+	var create = __webpack_require__(145);
+	var is = __webpack_require__(146);
+	var isArray = __webpack_require__(131);
 	
 	function getDefaultName(type) {
 	  return 'Array<' + getTypeName(type) + '>';
 	}
 	
 	function list(type, name) {
 	
 	  if (false) {
@@ -18667,30 +18742,30 @@ var Debugger =
 	  return List;
 	}
 	
 	list.getDefaultName = getDefaultName;
 	module.exports = list;
 
 
 /***/ },
-/* 154 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var isTypeName = __webpack_require__(141);
-	var isFunction = __webpack_require__(117);
-	var isMaybe = __webpack_require__(155);
-	var isIdentity = __webpack_require__(142);
-	var Any = __webpack_require__(122);
-	var create = __webpack_require__(143);
-	var Nil = __webpack_require__(136);
-	var forbidNewOperator = __webpack_require__(125);
-	var is = __webpack_require__(144);
-	var getTypeName = __webpack_require__(126);
+/* 157 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var isTypeName = __webpack_require__(143);
+	var isFunction = __webpack_require__(119);
+	var isMaybe = __webpack_require__(158);
+	var isIdentity = __webpack_require__(144);
+	var Any = __webpack_require__(124);
+	var create = __webpack_require__(145);
+	var Nil = __webpack_require__(138);
+	var forbidNewOperator = __webpack_require__(127);
+	var is = __webpack_require__(146);
+	var getTypeName = __webpack_require__(128);
 	
 	function getDefaultName(type) {
 	  return '?' + getTypeName(type);
 	}
 	
 	function maybe(type, name) {
 	
 	  if (isMaybe(type) || type === Any || type === Nil) { // makes the combinator idempotent and handle Any, Nil
@@ -18698,70 +18773,73 @@ var Debugger =
 	  }
 	
 	  if (false) {
 	    assert(isFunction(type), function () { return 'Invalid argument type ' + assert.stringify(type) + ' supplied to maybe(type, [name]) combinator (expected a type)'; });
 	    assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to maybe(type, [name]) combinator (expected a string)'; });
 	  }
 	
 	  var displayName = name || getDefaultName(type);
+	  var identity = isIdentity(type);
 	
 	  function Maybe(value, path) {
 	    if (false) {
-	      forbidNewOperator(this, Maybe);
+	      if (identity) {
+	        forbidNewOperator(this, Maybe);
+	      }
 	    }
 	    return Nil.is(value) ? value : create(type, value, path);
 	  }
 	
 	  Maybe.meta = {
 	    kind: 'maybe',
 	    type: type,
 	    name: name,
-	    identity: isIdentity(type)
+	    identity: identity
 	  };
 	
 	  Maybe.displayName = displayName;
 	
 	  Maybe.is = function (x) {
 	    return Nil.is(x) || is(x, type);
 	  };
 	
 	  return Maybe;
 	}
 	
 	maybe.getDefaultName = getDefaultName;
 	module.exports = maybe;
 
 
 /***/ },
-/* 155 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isType = __webpack_require__(127);
+/* 158 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isType = __webpack_require__(129);
 	
 	module.exports = function isMaybe(x) {
 	  return isType(x) && ( x.meta.kind === 'maybe' );
 	};
 
 /***/ },
-/* 156 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var isTypeName = __webpack_require__(141);
-	var String = __webpack_require__(147);
-	var Function = __webpack_require__(135);
-	var isBoolean = __webpack_require__(132);
-	var isObject = __webpack_require__(128);
-	var isNil = __webpack_require__(118);
-	var create = __webpack_require__(143);
-	var getTypeName = __webpack_require__(126);
-	var dict = __webpack_require__(149);
-	var getDefaultInterfaceName = __webpack_require__(157);
-	var extend = __webpack_require__(158);
+/* 159 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var isTypeName = __webpack_require__(143);
+	var String = __webpack_require__(149);
+	var Function = __webpack_require__(137);
+	var isBoolean = __webpack_require__(134);
+	var isObject = __webpack_require__(130);
+	var isNil = __webpack_require__(120);
+	var create = __webpack_require__(145);
+	var getTypeName = __webpack_require__(128);
+	var dict = __webpack_require__(151);
+	var getDefaultInterfaceName = __webpack_require__(160);
+	var extend = __webpack_require__(161);
 	
 	function getDefaultName(props) {
 	  return 'Struct' + getDefaultInterfaceName(props);
 	}
 	
 	function extendStruct(mixins, name) {
 	  return extend(struct, mixins, name);
 	}
@@ -18865,43 +18943,43 @@ var Debugger =
 	struct.strict = false;
 	struct.getOptions = getOptions;
 	struct.getDefaultName = getDefaultName;
 	struct.extend = extendStruct;
 	module.exports = struct;
 
 
 /***/ },
-/* 157 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getTypeName = __webpack_require__(126);
+/* 160 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var getTypeName = __webpack_require__(128);
 	
 	function getDefaultInterfaceName(props) {
 	  return '{' + Object.keys(props).map(function (prop) {
 	    return prop + ': ' + getTypeName(props[prop]);
 	  }).join(', ') + '}';
 	}
 	
 	module.exports = getDefaultInterfaceName;
 
 
 /***/ },
-/* 158 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var assert = __webpack_require__(116);
-	var isFunction = __webpack_require__(117);
-	var isArray = __webpack_require__(129);
-	var mixin = __webpack_require__(151);
-	var isStruct = __webpack_require__(159);
-	var isInterface = __webpack_require__(160);
-	var isObject = __webpack_require__(128);
-	var refinement = __webpack_require__(140);
-	var decompose = __webpack_require__(161);
+/* 161 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(118);
+	var isFunction = __webpack_require__(119);
+	var isArray = __webpack_require__(131);
+	var mixin = __webpack_require__(153);
+	var isStruct = __webpack_require__(162);
+	var isInterface = __webpack_require__(163);
+	var isObject = __webpack_require__(130);
+	var refinement = __webpack_require__(142);
+	var decompose = __webpack_require__(164);
 	
 	function compose(predicates, unrefinedType) {
 	  return predicates.reduce(function (type, predicate) {
 	    return refinement(type, predicate);
 	  }, unrefinedType);
 	}
 	
 	function getProps(type) {
@@ -18929,52 +19007,52 @@ var Debugger =
 	    var decomposition = decompose(x);
 	    var unrefinedType = decomposition.unrefinedType;
 	    if (false) {
 	      assert(isObject(unrefinedType) || isStruct(unrefinedType) || isInterface(unrefinedType), function () { return 'Invalid argument mixins[' + i + '] supplied to extend(combinator, mixins, options), expected an object, struct, interface or a refinement (of struct or interface)'; });
 	    }
 	    pushAll(predicates, decomposition.predicates);
 	    mixin(props, getProps(unrefinedType));
 	    mixin(prototype, unrefinedType.prototype);
-	    mixin(defaultProps, getDefaultProps(unrefinedType));
+	    mixin(defaultProps, getDefaultProps(unrefinedType), true);
 	  });
 	  options = combinator.getOptions(options);
-	  mixin(options.defaultProps, defaultProps);
+	  options.defaultProps = mixin(defaultProps, options.defaultProps, true);
 	  var result = compose(predicates, combinator(props, options));
 	  mixin(result.prototype, prototype);
 	  return result;
 	}
 	
 	module.exports = extend;
 
 /***/ },
-/* 159 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isType = __webpack_require__(127);
+/* 162 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isType = __webpack_require__(129);
 	
 	module.exports = function isStruct(x) {
 	  return isType(x) && ( x.meta.kind === 'struct' );
 	};
 
 /***/ },
-/* 160 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isType = __webpack_require__(127);
+/* 163 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isType = __webpack_require__(129);
 	
 	module.exports = function isInterface(x) {
 	  return isType(x) && ( x.meta.kind === 'interface' );
 	};
 
 /***/ },
-/* 161 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var isType = __webpack_require__(127);
+/* 164 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isType = __webpack_require__(129);
 	
 	function isRefinement(type) {
 	  return isType(type) && type.meta.kind === 'subtype';
 	}
 	
 	function getPredicates(type) {
 	  return isRefinement(type) ?
 	    [type.meta.predicate].concat(getPredicates(type.meta.type)) :
@@ -18992,27 +19070,27 @@ var Debugger =
 	    predicates: getPredicates(type),
 	    unrefinedType: getUnrefinedType(type)
 	  };
 	}
 	
 	module.exports = decompose;
 
 /***/ },
-/* 162 */
-/***/ function(module, exports, __webpack_require__) {