Bug 1372694 - Stop making the default theme a heavyweight theme. r=kmag,aswan
authorTim Nguyen <ntim.bugs@gmail.com>
Sun, 01 Apr 2018 13:53:31 +0200
changeset 468738 0819fc14fc57f1a10a9aaf179882a532ac2f6835
parent 468737 9b20ccf5448b55feef48f9830268b7acf53eac75
child 468739 6bb7337970f19723f9ba34a682b4682c53863e5a
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag, aswan
bugs1372694
milestone61.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
Bug 1372694 - Stop making the default theme a heavyweight theme. r=kmag,aswan MozReview-Commit-ID: 30wMauuc9oo
browser/app/moz.build
browser/app/profile/extensions/moz.build
browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf.in
browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/moz.build
browser/app/profile/firefox.js
browser/base/content/default-theme-icon.svg
browser/base/content/moz.build
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_bug592338.js
browser/base/jar.mn
browser/components/customizableui/CustomizableUI.jsm
browser/components/customizableui/CustomizeMode.jsm
browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
browser/components/customizableui/test/browser_970511_undo_restore_default.js
browser/installer/allowed-dupes.mn
browser/installer/package-manifest.in
browser/locales/en-US/chrome/browser/browser.properties
browser/themes/linux/jar.mn
browser/themes/osx/jar.mn
browser/themes/shared/customizableui/customizeMode.inc.css
browser/themes/windows/jar.mn
security/manager/ssl/tests/unit/xpcshell.ini
services/sync/tests/unit/test_prefs_store.js
toolkit/components/extensions/test/browser/browser_ext_management_themes.js
toolkit/components/extensions/test/xpcshell/test_ext_management.js
toolkit/components/telemetry/tests/unit/xpcshell.ini
toolkit/locales/en-US/chrome/global/extensions.properties
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/LightweightThemeManager.jsm
toolkit/mozapps/extensions/content/default-theme-icon.svg
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
toolkit/mozapps/extensions/internal/XPIInstall.jsm
toolkit/mozapps/extensions/internal/XPIProvider.jsm
toolkit/mozapps/extensions/internal/XPIProviderUtils.js
toolkit/mozapps/extensions/jar.mn
toolkit/mozapps/extensions/test/browser/browser.ini
toolkit/mozapps/extensions/test/xpcshell/head_addons.js
toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js
toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js
toolkit/mozapps/extensions/test/xpcshell/test_addonStartup.js
toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js
toolkit/mozapps/extensions/test/xpcshell/test_badschema.js
toolkit/mozapps/extensions/test/xpcshell/test_manifest.js
toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js
toolkit/mozapps/extensions/test/xpcshell/test_webextension_theme.js
toolkit/mozapps/extensions/test/xpinstall/browser.ini
toolkit/mozapps/extensions/test/xpinstall/theme.xpi
toolkit/themes/linux/mozapps/jar.mn
toolkit/themes/osx/global/jar.mn
toolkit/themes/osx/mozapps/jar.mn
toolkit/themes/shared/non-mac.jar.inc.mn
toolkit/themes/windows/global/jar.mn
toolkit/themes/windows/mozapps/jar.mn
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -19,26 +19,21 @@ with Files("macversion.py"):
 with Files("macbuild/**"):
     BUG_COMPONENT = ("Core", "Widget: Cocoa")
 
 with Files("moz.build"):
     BUG_COMPONENT = ("Firefox Build System", "General")
 with Files("Makefile.in"):
     BUG_COMPONENT = ("Firefox Build System", "General")
 
-with Files("profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/**"):
-    BUG_COMPONENT = ("Firefox", "Theme")
 with Files("profile/channel-prefs.js"):
     BUG_COMPONENT = ("Firefox", "Installer")
 with Files("profile/firefox.js"):
     BUG_COMPONENT = ("Firefox", "General")
 
-
-DIRS += ['profile/extensions']
-
 GeckoProgram(CONFIG['MOZ_APP_NAME'])
 
 SOURCES += [
     'nsBrowserApp.cpp',
 ]
 
 # Neither channel-prefs.js nor firefox.exe want to end up in dist/bin/browser.
 DIST_SUBDIR = ""
deleted file mode 100644
--- a/browser/app/profile/extensions/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- 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/.
-
-DIRS += ['{972ce4c6-7e08-4474-a285-3208198ce6fd}']
deleted file mode 100644
--- a/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf.in
+++ /dev/null
@@ -1,42 +0,0 @@
-<?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/. -->
-
-
-#filter substitution
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>{972ce4c6-7e08-4474-a285-3208198ce6fd}</em:id>
-    <em:version>@FIREFOX_VERSION@</em:version>
-
-    <!-- Target Application this theme can install into,
-        with minimum and maximum supported versions. -->
-    <em:targetApplication>
-      <Description>
-        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>@FIREFOX_VERSION@</em:minVersion>
-        <em:maxVersion>@FIREFOX_VERSION@</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>Default</em:name>
-    <em:description>The default theme.</em:description>
-
-    <!-- Front End Integration Hooks (used by Theme Manager)-->
-    <em:creator>Mozilla</em:creator>
-    <em:contributor>Mozilla Contributors</em:contributor>
-
-    <!-- Allow lightweight themes to apply to this theme -->
-    <em:skinnable>true</em:skinnable>
-
-    <em:internalName>classic/1.0</em:internalName>
-
-    <em:iconURL>chrome://browser/content/default-theme-icon.svg</em:iconURL>
-  </Description>
-
-</RDF>
deleted file mode 100644
--- a/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/moz.build
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- 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/.
-
-FINAL_TARGET = 'dist/bin/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}'
-
-FINAL_TARGET_PP_FILES += [
-    'install.rdf.in',
-]
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -76,17 +76,17 @@ pref("extensions.geckoProfiler.getSymbol
 pref("extensions.webextensions.base-content-security-policy", "script-src 'self' https://* moz-extension: blob: filesystem: 'unsafe-eval' 'unsafe-inline'; object-src 'self' https://* moz-extension: blob: filesystem:;");
 pref("extensions.webextensions.default-content-security-policy", "script-src 'self'; object-src 'self';");
 
 #if defined(XP_WIN) || defined(XP_MACOSX)
 pref("extensions.webextensions.remote", true);
 #endif
 
 // Extensions that should not be flagged as legacy in about:addons
-pref("extensions.legacy.exceptions", "{972ce4c6-7e08-4474-a285-3208198ce6fd},testpilot@cliqz.com,@testpilot-containers,jid1-NeEaf3sAHdKHPA@jetpack,@activity-streams,pulse@mozilla.com,@testpilot-addon,@min-vid,tabcentertest1@mozilla.com,snoozetabs@mozilla.com,speaktome@mozilla.com,hoverpad@mozilla.com");
+pref("extensions.legacy.exceptions", "testpilot@cliqz.com,@testpilot-containers,jid1-NeEaf3sAHdKHPA@jetpack,@activity-streams,pulse@mozilla.com,@testpilot-addon,@min-vid,tabcentertest1@mozilla.com,snoozetabs@mozilla.com,speaktome@mozilla.com,hoverpad@mozilla.com");
 
 // Require signed add-ons by default
 pref("extensions.langpacks.signatures.required", true);
 pref("xpinstall.signatures.required", true);
 pref("xpinstall.signatures.devInfoURL", "https://wiki.mozilla.org/Addons/Extension_Signing");
 
 // Dictionary download preference
 pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/firefox/dictionaries/");
@@ -185,19 +185,16 @@ pref("app.update.service.enabled", true)
 //  .. etc ..
 //
 pref("extensions.update.enabled", true);
 pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
 pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
 pref("extensions.update.interval", 86400);  // Check for updates to Extensions and
                                             // Themes every day
 
-pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name", "chrome://browser/locale/browser.properties");
-pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description", "chrome://browser/locale/browser.properties");
-
 pref("extensions.webextensions.themes.enabled", true);
 pref("extensions.webextensions.themes.icons.buttons", "back,forward,reload,stop,bookmark_star,bookmark_menu,downloads,home,app_menu,cut,copy,paste,new_window,new_private_window,save_page,print,history,full_screen,find,options,addons,developer,synced_tabs,open_file,sidebars,share_page,subscribe,text_encoding,email_link,forget,pocket");
 
 pref("lightweightThemes.update.enabled", true);
 pref("lightweightThemes.getMoreURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes");
 pref("lightweightThemes.recommendedThemes", "[{\"id\":\"recommended-1\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/a-web-browser-renaissance/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.header.jpg\",\"textcolor\":\"#000000\",\"accentcolor\":\"#834d29\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.preview.jpg\",\"author\":\"Sean.Martell\",\"version\":\"0\"},{\"id\":\"recommended-2\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/space-fantasy/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.header.jpg\",\"textcolor\":\"#ffffff\",\"accentcolor\":\"#d9d9d9\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.preview.jpg\",\"author\":\"fx5800p\",\"version\":\"1.0\"},{\"id\":\"recommended-4\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/pastel-gradient/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.header.png\",\"textcolor\":\"#000000\",\"accentcolor\":\"#000000\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.preview.png\",\"author\":\"darrinhenein\",\"version\":\"1.0\"}]");
 
 #if defined(MOZ_WIDEVINE_EME)
@@ -1252,17 +1249,17 @@ pref("services.sync.prefs.sync.xpinstall
 // user's tabs and bookmarks. Note this pref is also synced.
 pref("services.sync.syncedTabs.showRemoteIcons", true);
 
 // Developer edition preferences
 #ifdef MOZ_DEV_EDITION
 pref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org",
      sticky);
 #else
-pref("lightweightThemes.selectedThemeID", "", sticky);
+pref("lightweightThemes.selectedThemeID", "default-theme@mozilla.org", sticky);
 #endif
 
 // Whether the character encoding menu is under the main Firefox button. This
 // preference is a string so that localizers can alter it.
 pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");
 
 // Allow using tab-modal prompts when possible.
 pref("prompts.tab_modal.enabled", true);
--- a/browser/base/content/moz.build
+++ b/browser/base/content/moz.build
@@ -141,19 +141,16 @@ with Files("browser-sync.js"):
     BUG_COMPONENT = ("Firefox", "Sync")
 
 with Files("browser-tabPreviews.xml"):
     BUG_COMPONENT = ("Firefox", "Tabbed Browser")
 
 with Files("contentSearch*"):
     BUG_COMPONENT = ("Firefox", "Search")
 
-with Files("*.svg"):
-    BUG_COMPONENT = ("Firefox", "Theme")
-
 with Files("hiddenWindow.xul"):
     BUG_COMPONENT = ("Firefox", "Device Permissions")
 
 with Files("macWindow.inc.xul"):
     BUG_COMPONENT = ("Firefox", "Shell Integration")
 
 with Files("tabbrowser*"):
     BUG_COMPONENT = ("Firefox", "Tabbed Browser")
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -73,17 +73,16 @@ support-files =
   video.ogg
   web_video.html
   web_video1.ogv
   web_video1.ogv^headers^
   zoom_test.html
   !/image/test/mochitest/blue.png
   !/toolkit/content/tests/browser/common/mockTransfer.js
   !/toolkit/modules/tests/browser/metadata_*.html
-  !/toolkit/mozapps/extensions/test/xpinstall/theme.xpi
 
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_addKeywordSearch.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_alltabslistener.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_audioTabIcon.js]
 tags = audiochannel
@@ -206,18 +205,16 @@ skip-if = toolkit != "cocoa" # Because o
 [browser_bug581242.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug581253.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug585785.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug585830.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
-[browser_bug592338.js]
-# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug594131.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug596687.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug597218.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug609700.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
deleted file mode 100644
--- a/browser/base/content/test/general/browser_bug592338.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-const TESTROOT = "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/";
-
-const {LightweightThemeManager} = ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm", {});
-
-/**
- * Wait for the given PopupNotification to display
- *
- * @param {string} name
- *        The name of the notification to wait for.
- *
- * @returns {Promise}
- *          Resolves with the notification window.
- */
-function promisePopupNotificationShown(name) {
-  return new Promise(resolve => {
-    function popupshown() {
-      let notification = PopupNotifications.getNotification(name);
-      if (!notification) { return; }
-
-      ok(notification, `${name} notification shown`);
-      ok(PopupNotifications.isPanelOpen, "notification panel open");
-
-      PopupNotifications.panel.removeEventListener("popupshown", popupshown);
-      resolve(PopupNotifications.panel.firstChild);
-    }
-
-    PopupNotifications.panel.addEventListener("popupshown", popupshown);
-  });
-}
-
-
-var TESTS = [
-function test_install_http() {
-  is(LightweightThemeManager.currentTheme, null, "Should be no lightweight theme selected");
-
-  var pm = Services.perms;
-  pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION);
-
-  // NB: Not https so no installs allowed.
-  const URL = "http://example.org/browser/browser/base/content/test/general/bug592338.html";
-  BrowserTestUtils.openNewForegroundTab({ gBrowser, url: URL }).then(async function() {
-    let prompted = promisePopupNotificationShown("addon-webext-permissions");
-    BrowserTestUtils.synthesizeMouse("#theme-install", 2, 2, {}, gBrowser.selectedBrowser);
-    await prompted;
-
-    is(LightweightThemeManager.currentTheme, null, "Should not have installed the test theme");
-
-    gBrowser.removeTab(gBrowser.selectedTab);
-
-    pm.remove(makeURI("http://example.org/"), "install");
-
-    runNextTest();
-  });
-},
-
-function test_install_lwtheme() {
-  is(LightweightThemeManager.currentTheme, null, "Should be no lightweight theme selected");
-
-  var pm = Services.perms;
-  pm.add(makeURI("https://example.com/"), "install", pm.ALLOW_ACTION);
-
-  const URL = "https://example.com/browser/browser/base/content/test/general/bug592338.html";
-  BrowserTestUtils.openNewForegroundTab({ gBrowser, url: URL }).then(() => {
-    let promise = promisePopupNotificationShown("addon-installed");
-    BrowserTestUtils.synthesizeMouse("#theme-install", 2, 2, {}, gBrowser.selectedBrowser);
-    promise.then(() => {
-      is(LightweightThemeManager.currentTheme.id, "test", "Should have installed the test theme");
-
-      LightweightThemeManager.currentTheme = null;
-      gBrowser.removeTab(gBrowser.selectedTab);
-      Services.perms.remove(makeURI("http://example.com/"), "install");
-
-      runNextTest();
-    });
-  });
-}
-];
-
-async function runNextTest() {
-  let aInstalls = await AddonManager.getAllInstalls();
-  is(aInstalls.length, 0, "Should be no active installs");
-
-  if (TESTS.length == 0) {
-    let aAddon = await AddonManager.getAddonByID("theme-xpi@tests.mozilla.org");
-    aAddon.uninstall();
-
-    Services.prefs.setBoolPref("extensions.logging.enabled", false);
-
-    finish();
-    return;
-  }
-
-  info("Running " + TESTS[0].name);
-  TESTS.shift()();
-}
-
-async function test() {
-  waitForExplicitFinish();
-
-  Services.prefs.setBoolPref("extensions.logging.enabled", true);
-
-  let aInstall = await AddonManager.getInstallForURL(TESTROOT + "theme.xpi", "application/x-xpinstall");
-  aInstall.addListener({
-    async onInstallEnded() {
-      let aAddon = await AddonManager.getAddonByID("theme-xpi@tests.mozilla.org");
-      isnot(aAddon, null, "Should have installed the test theme.");
-
-      runNextTest();
-    }
-  });
-
-  aInstall.install();
-}
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -71,34 +71,33 @@ browser.jar:
         content/browser/browser-sync.js               (content/browser-sync.js)
 *       content/browser/browser-tabPreviews.xml       (content/browser-tabPreviews.xml)
         content/browser/browser-tabsintitlebar.js       (content/browser-tabsintitlebar.js)
         content/browser/browser-thumbnails.js         (content/browser-thumbnails.js)
         content/browser/browser-trackingprotection.js (content/browser-trackingprotection.js)
         content/browser/browser-webrender.js          (content/browser-webrender.js)
         content/browser/tab-content.js                (content/tab-content.js)
         content/browser/content.js                    (content/content.js)
-        content/browser/default-theme-icon.svg        (content/default-theme-icon.svg)
         content/browser/defaultthemes/1.header.jpg    (content/defaultthemes/1.header.jpg)
         content/browser/defaultthemes/1.icon.jpg      (content/defaultthemes/1.icon.jpg)
         content/browser/defaultthemes/1.preview.jpg   (content/defaultthemes/1.preview.jpg)
         content/browser/defaultthemes/2.header.jpg    (content/defaultthemes/2.header.jpg)
         content/browser/defaultthemes/2.icon.jpg      (content/defaultthemes/2.icon.jpg)
         content/browser/defaultthemes/2.preview.jpg   (content/defaultthemes/2.preview.jpg)
         content/browser/defaultthemes/3.header.png    (content/defaultthemes/3.header.png)
         content/browser/defaultthemes/3.icon.png      (content/defaultthemes/3.icon.png)
         content/browser/defaultthemes/3.preview.png   (content/defaultthemes/3.preview.png)
         content/browser/defaultthemes/4.header.png    (content/defaultthemes/4.header.png)
         content/browser/defaultthemes/4.icon.png      (content/defaultthemes/4.icon.png)
         content/browser/defaultthemes/4.preview.png   (content/defaultthemes/4.preview.png)
         content/browser/defaultthemes/5.header.png    (content/defaultthemes/5.header.png)
         content/browser/defaultthemes/5.icon.jpg      (content/defaultthemes/5.icon.jpg)
         content/browser/defaultthemes/5.preview.jpg   (content/defaultthemes/5.preview.jpg)
-        content/browser/defaultthemes/dark.icon.svg  (content/defaultthemes/dark.icon.svg)
-        content/browser/defaultthemes/light.icon.svg (content/defaultthemes/light.icon.svg)
+        content/browser/defaultthemes/dark.icon.svg   (content/defaultthemes/dark.icon.svg)
+        content/browser/defaultthemes/light.icon.svg  (content/defaultthemes/light.icon.svg)
 *       content/browser/pageinfo/pageInfo.xul         (content/pageinfo/pageInfo.xul)
         content/browser/pageinfo/pageInfo.js          (content/pageinfo/pageInfo.js)
         content/browser/pageinfo/pageInfo.css         (content/pageinfo/pageInfo.css)
         content/browser/pageinfo/feeds.js             (content/pageinfo/feeds.js)
         content/browser/pageinfo/permissions.js       (content/pageinfo/permissions.js)
         content/browser/pageinfo/security.js          (content/pageinfo/security.js)
         content/browser/robot.ico                     (content/robot.ico)
         content/browser/static-robot.png              (content/static-robot.png)
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -2900,17 +2900,18 @@ var CustomizableUIInternal = {
       return false;
     }
 
     if (Services.prefs.prefHasUserValue(kPrefExtraDragSpace)) {
       log.debug(kPrefExtraDragSpace + " pref is non-default");
       return false;
     }
 
-    if (LightweightThemeManager.currentTheme) {
+    if (LightweightThemeManager.currentTheme &&
+        LightweightThemeManager.currentTheme.id != "default-theme@mozilla.org") {
       log.debug(LightweightThemeManager.currentTheme + " theme is non-default");
       return false;
     }
 
     return true;
   },
 
   setToolbarVisibility(aToolbarId, aIsVisible) {
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -1334,18 +1334,18 @@ CustomizeMode.prototype = {
   updateAutoTouchMode(checked) {
     Services.prefs.setBoolPref("browser.touchmode.auto", checked);
     // Re-render the menu items since the active mode might have
     // change because of this.
     this.onUIDensityMenuShowing();
     this._onUIChange();
   },
 
-  async onLWThemesMenuShowing(aEvent) {
-    const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
+  onLWThemesMenuShowing(aEvent) {
+    const DEFAULT_THEME_ID = "default-theme@mozilla.org";
     const LIGHT_THEME_ID = "firefox-compact-light@mozilla.org";
     const DARK_THEME_ID = "firefox-compact-dark@mozilla.org";
     const MAX_THEME_COUNT = 6;
 
     this._clearLWThemesMenu(aEvent.target);
 
     function previewTheme(aPreviewThemeEvent) {
       LightweightThemeManager.previewTheme(
@@ -1358,31 +1358,23 @@ CustomizeMode.prototype = {
     }
 
     let onThemeSelected = panel => {
       this._updateLWThemeButtonIcon();
       this._onUIChange();
       panel.hidePopup();
     };
 
-    let aDefaultTheme = await AddonManager.getAddonByID(DEFAULT_THEME_ID);
     let doc = this.window.document;
 
     function buildToolbarButton(aTheme) {
       let tbb = doc.createElement("toolbarbutton");
       tbb.theme = aTheme;
       tbb.setAttribute("label", aTheme.name);
-      if (aDefaultTheme == aTheme) {
-        // The actual icon is set up so it looks nice in about:addons, but
-        // we'd like the version that's correct for the OS we're on, so we set
-        // an attribute that our styling will then use to display the icon.
-        tbb.setAttribute("defaulttheme", "true");
-      } else {
-        tbb.setAttribute("image", aTheme.iconURL);
-      }
+      tbb.setAttribute("image", aTheme.iconURL);
       if (aTheme.description)
         tbb.setAttribute("tooltiptext", aTheme.description);
       tbb.setAttribute("tabindex", "0");
       tbb.classList.add("customization-lwtheme-menu-theme");
       let isActive = activeThemeID == aTheme.id;
       tbb.setAttribute("aria-checked", isActive);
       tbb.setAttribute("role", "menuitemradio");
       if (isActive) {
@@ -1391,24 +1383,24 @@ CustomizeMode.prototype = {
       tbb.addEventListener("focus", previewTheme);
       tbb.addEventListener("mouseover", previewTheme);
       tbb.addEventListener("blur", resetPreview);
       tbb.addEventListener("mouseout", resetPreview);
 
       return tbb;
     }
 
-    let themes = [aDefaultTheme];
+    let themes = [];
     let lwts = LightweightThemeManager.usedThemes;
     let currentLwt = LightweightThemeManager.currentTheme;
 
     let activeThemeID = currentLwt ? currentLwt.id : DEFAULT_THEME_ID;
 
     // Move the current theme (if any) and the light/dark themes to the start:
-    let importantThemes = [LIGHT_THEME_ID, DARK_THEME_ID];
+    let importantThemes = [DEFAULT_THEME_ID, LIGHT_THEME_ID, DARK_THEME_ID];
     if (currentLwt && !importantThemes.includes(currentLwt.id)) {
       importantThemes.push(currentLwt.id);
     }
     for (let importantTheme of importantThemes) {
       let themeIndex = lwts.findIndex(theme => theme.id == importantTheme);
       if (themeIndex > -1) {
         themes.push(...lwts.splice(themeIndex, 1));
       }
--- a/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
+++ b/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
@@ -1,15 +1,15 @@
 /* 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 DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
+const DEFAULT_THEME_ID = "default-theme@mozilla.org";
 const LIGHT_THEME_ID = "firefox-compact-light@mozilla.org";
 const DARK_THEME_ID = "firefox-compact-dark@mozilla.org";
 const {LightweightThemeManager} = ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm", {});
 
 add_task(async function() {
   Services.prefs.clearUserPref("lightweightThemes.usedThemes");
   Services.prefs.clearUserPref("lightweightThemes.recommendedThemes");
 
@@ -90,33 +90,34 @@ add_task(async function() {
     themeCount++;
     iterNode = iterNode.nextSibling;
   }
   is(themeCount, 4,
      "There should be four themes in the 'My Themes' section");
 
   let defaultTheme = header.nextSibling;
   defaultTheme.doCommand();
-  is(Services.prefs.getCharPref("lightweightThemes.selectedThemeID"), "", "No lwtheme should be selected");
+  is(Services.prefs.getCharPref("lightweightThemes.selectedThemeID"),
+     DEFAULT_THEME_ID, "Default theme should be selected");
 
   // ensure current theme isn't set to "Default"
   popupShownPromise = popupShown(popup);
   EventUtils.synthesizeMouseAtCenter(themesButton, {});
   info("Clicked on themes button a fourth time");
   await popupShownPromise;
 
   firstLWTheme = recommendedHeader.nextSibling;
   themeChangedPromise = promiseObserverNotified("lightweight-theme-changed");
   firstLWTheme.doCommand();
   info("Clicked on first theme again");
   await themeChangedPromise;
 
   // check that "Restore Defaults" button resets theme
   await gCustomizeMode.reset();
-  is(LightweightThemeManager.currentTheme, null, "Current theme reset to default");
+  is(LightweightThemeManager.currentTheme.id, DEFAULT_THEME_ID, "Current theme reset to default");
 
   await endCustomizing();
   Services.prefs.setCharPref("lightweightThemes.usedThemes", "[]");
   Services.prefs.setCharPref("lightweightThemes.recommendedThemes", "[]");
   info("Removed all recommended themes");
   await startCustomizing();
   popupShownPromise = popupShown(popup);
   EventUtils.synthesizeMouseAtCenter(themesButton, {});
--- a/browser/components/customizableui/test/browser_970511_undo_restore_default.js
+++ b/browser/components/customizableui/test/browser_970511_undo_restore_default.js
@@ -32,17 +32,17 @@ add_task(async function() {
   await themeChangedPromise;
 
   is(LightweightThemeManager.currentTheme.id, firstLWThemeId, "Theme changed to first option");
 
   await gCustomizeMode.reset();
 
   ok(CustomizableUI.inDefaultState, "In default state after reset");
   is(undoResetButton.hidden, false, "The undo button is visible after reset");
-  is(LightweightThemeManager.currentTheme, null, "Theme reset to default");
+  is(LightweightThemeManager.currentTheme.id, "default-theme@mozilla.org", "Theme reset to default");
 
   await gCustomizeMode.undoReset();
 
   is(LightweightThemeManager.currentTheme.id, firstLWThemeId, "Theme has been reset from default to original choice");
   ok(!CustomizableUI.inDefaultState, "Not in default state after undo-reset");
   is(undoResetButton.hidden, true, "The undo button is hidden after clicking on the undo button");
   is(CustomizableUI.getPlacementOfWidget(homeButtonId), null, "Home button is in palette");
 
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -76,17 +76,16 @@ browser/chrome/icons/default/default128.
 browser/chrome/pdfjs/content/web/images/findbarButton-next-rtl.png
 browser/chrome/pdfjs/content/web/images/findbarButton-next-rtl@2x.png
 browser/chrome/pdfjs/content/web/images/findbarButton-next.png
 browser/chrome/pdfjs/content/web/images/findbarButton-next@2x.png
 browser/chrome/pdfjs/content/web/images/findbarButton-previous-rtl.png
 browser/chrome/pdfjs/content/web/images/findbarButton-previous-rtl@2x.png
 browser/chrome/pdfjs/content/web/images/findbarButton-previous.png
 browser/chrome/pdfjs/content/web/images/findbarButton-previous@2x.png
-browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png
 browser/features/firefox@getpocket.com/chrome/skin/linux/menuPanel.png
 browser/features/firefox@getpocket.com/chrome/skin/linux/menuPanel@2x.png
 browser/features/firefox@getpocket.com/chrome/skin/windows/menuPanel.png
 browser/features/firefox@getpocket.com/chrome/skin/windows/menuPanel@2x.png
 chrome.manifest
 chrome/toolkit/skin/classic/global/autocomplete.css
 chrome/toolkit/skin/classic/global/button.css
 chrome/toolkit/skin/classic/global/checkbox.css
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -399,18 +399,16 @@
 #endif
 
 ; [Browser Chrome Files]
 @RESPATH@/browser/chrome.manifest
 @RESPATH@/browser/chrome/browser@JAREXT@
 @RESPATH@/browser/chrome/browser.manifest
 @RESPATH@/browser/chrome/pdfjs.manifest
 @RESPATH@/browser/chrome/pdfjs/*
-@RESPATH@/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/chrome.manifest
-@RESPATH@/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
 @RESPATH@/chrome/toolkit@JAREXT@
 @RESPATH@/chrome/toolkit.manifest
 @RESPATH@/chrome/recording.manifest
 @RESPATH@/chrome/recording/*
 #ifdef MOZ_GTK
 @RESPATH@/browser/chrome/icons/default/default16.png
 @RESPATH@/browser/chrome/icons/default/default32.png
 @RESPATH@/browser/chrome/icons/default/default48.png
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -620,19 +620,16 @@ safebrowsing.reportedHarmfulSite=Reporte
 # of tabs in the current browser window. It will always be 2 at least.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
 ctrlTab.listAllTabs.label=;List All #1 Tabs
 
 # LOCALIZATION NOTE (addKeywordTitleAutoFill): %S will be replaced by the page's title
 # Used as the bookmark name when saving a keyword for a search field.
 addKeywordTitleAutoFill=Search %S
 
-extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name=Default
-extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description=The default theme.
-
 # safeModeRestart
 safeModeRestartPromptTitle=Restart with Add-ons Disabled
 safeModeRestartPromptMessage=Are you sure you want to disable all add-ons and restart?
 safeModeRestartButton=Restart
 
 # LOCALIZATION NOTE (browser.menu.showCharacterEncoding): Set to the string
 # "true" (spelled and capitalized exactly that way) to show the "Text
 # Encoding" menu in the main Firefox button on Windows. Any other value will
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -45,13 +45,12 @@ browser.jar:
   skin/classic/browser/preferences/preferences.css    (preferences/preferences.css)
 * skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
 * skin/classic/browser/preferences/in-content/dialog.css      (preferences/in-content/dialog.css)
   skin/classic/browser/preferences/applications.css   (preferences/applications.css)
   skin/classic/browser/tabbrowser/tabDragIndicator.png      (tabbrowser/tabDragIndicator.png)
 
   skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
 
-[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
 % override chrome://browser/skin/feeds/audioFeedIcon.png              chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/audioFeedIcon16.png            chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/feeds/videoFeedIcon.png              chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/videoFeedIcon16.png            chrome://browser/skin/feeds/feedIcon16.png
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -56,14 +56,13 @@ browser.jar:
 * skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
 * skin/classic/browser/preferences/in-content/dialog.css      (preferences/in-content/dialog.css)
   skin/classic/browser/preferences/applications.css         (preferences/applications.css)
   skin/classic/browser/share.svg                            (share.svg)
   skin/classic/browser/tabbrowser/tabDragIndicator.png                   (tabbrowser/tabDragIndicator.png)
   skin/classic/browser/tabbrowser/tabDragIndicator@2x.png                (tabbrowser/tabDragIndicator@2x.png)
   skin/classic/browser/e10s-64@2x.png                                  (../shared/e10s-64@2x.png)
 
-[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
 % override chrome://browser/skin/feeds/audioFeedIcon.png                   chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/audioFeedIcon16.png                 chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/feeds/videoFeedIcon.png                   chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/videoFeedIcon16.png                 chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/notification-icons/geo-detailed.svg       chrome://browser/skin/notification-icons/geo.svg
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -153,17 +153,17 @@
 #customization-lwtheme-button > .box-inherit > .box-inherit > .button-icon {
   width: 16px;
   height: 16px;
   border-radius: 2px;
   background-size: contain;
 }
 
 #customization-lwtheme-button > .box-inherit > .box-inherit > .button-icon {
-  background-image: url("chrome://browser/content/default-theme-icon.svg");
+  background-image: url("chrome://mozapps/content/extensions/default-theme-icon.svg");
 }
 
 #customization-uidensity-button > .box-inherit > .box-inherit > .button-icon {
   background-image: url("chrome://browser/skin/customizableui/density-normal.svg");
 }
 
 #widget-overflow-fixed-list > toolbarpaletteitem[place="menu-panel"],
 toolbarpaletteitem[place="toolbar"] {
@@ -329,20 +329,16 @@ toolbarpaletteitem[place=toolbar] > tool
   padding-bottom: 0;
   padding-inline-start: 0;
 }
 
 .customization-uidensity-menuitem {
   color: inherit;
 }
 
-.customization-lwtheme-menu-theme[defaulttheme] {
-  list-style-image: url(chrome://browser/content/default-theme-icon.svg);
-}
-
 #customization-uidensity-menuitem-normal {
   list-style-image: url("chrome://browser/skin/customizableui/density-normal.svg");
 }
 
 #customization-uidensity-menuitem-compact {
   list-style-image: url("chrome://browser/skin/customizableui/density-compact.svg");
 }
 
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -56,14 +56,13 @@ browser.jar:
   skin/classic/browser/window-controls/minimize.svg              (window-controls/minimize.svg)
   skin/classic/browser/window-controls/minimize-highcontrast.svg (window-controls/minimize-highcontrast.svg)
   skin/classic/browser/window-controls/minimize-themes.svg       (window-controls/minimize-themes.svg)
   skin/classic/browser/window-controls/restore.svg               (window-controls/restore.svg)
   skin/classic/browser/window-controls/restore-highcontrast.svg  (window-controls/restore-highcontrast.svg)
   skin/classic/browser/window-controls/restore-themes.svg        (window-controls/restore-themes.svg)
   skin/classic/browser/e10s-64@2x.png                            (../shared/e10s-64@2x.png)
 
-[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
 % override chrome://browser/skin/page-livemarks.png                   chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/feeds/audioFeedIcon.png              chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/audioFeedIcon16.png            chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/feeds/videoFeedIcon.png              chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/videoFeedIcon16.png            chrome://browser/skin/feeds/feedIcon16.png
--- a/security/manager/ssl/tests/unit/xpcshell.ini
+++ b/security/manager/ssl/tests/unit/xpcshell.ini
@@ -1,11 +1,12 @@
 [DEFAULT]
 head = head_psm.js
 tags = psm
+firefox-appdir = browser
 support-files =
   bad_certs/**
   ocsp_certs/**
   test_baseline_requirements/**
   test_broken_fips/**
   test_cert_eku/**
   test_cert_embedded_null/**
   test_cert_isBuiltInRoot_reload/**
--- a/services/sync/tests/unit/test_prefs_store.js
+++ b/services/sync/tests/unit/test_prefs_store.js
@@ -104,18 +104,17 @@ add_task(async function run_test() {
     Assert.equal(prefs.get("testing.synced.url"), "https://www.example.com");
     Assert.equal(prefs.get("testing.unsynced.url"), "https://www.example.com/2");
     Assert.equal(Svc.Prefs.get("prefs.sync.testing.somepref"), true);
 
     _("Enable persona");
     // Ensure we don't go to the network to fetch personas and end up leaking
     // stuff.
     Services.io.offline = true;
-    Assert.ok(!prefs.get("lightweightThemes.selectedThemeID"));
-    Assert.equal(LightweightThemeManager.currentTheme, null);
+    Assert.equal(LightweightThemeManager.currentTheme.id, "default-theme@mozilla.org");
 
     let persona1 = makePersona();
     let persona2 = makePersona();
     let usedThemes = JSON.stringify([persona1, persona2]);
     record.value = {
       "lightweightThemes.selectedThemeID": persona1.id,
       "lightweightThemes.usedThemes": usedThemes
     };
@@ -125,18 +124,17 @@ add_task(async function run_test() {
               persona1));
 
     _("Disable persona");
     record.value = {
       "lightweightThemes.selectedThemeID": null,
       "lightweightThemes.usedThemes": usedThemes
     };
     await store.update(record);
-    Assert.ok(!prefs.get("lightweightThemes.selectedThemeID"));
-    Assert.equal(LightweightThemeManager.currentTheme, null);
+    Assert.equal(LightweightThemeManager.currentTheme.id, "default-theme@mozilla.org");
 
     _("Only the current app's preferences are applied.");
     record = new PrefRec("prefs", "some-fake-app");
     record.value = {
       "testing.int": 98
     };
     await store.update(record);
     Assert.equal(prefs.get("testing.int"), 42);
--- a/toolkit/components/extensions/test/browser/browser_ext_management_themes.js
+++ b/toolkit/components/extensions/test/browser/browser_ext_management_themes.js
@@ -119,17 +119,16 @@ add_task(async function test_management_
     homepageURL: "http://mochi.test:8888/data/index.html",
     headerURL: "http://mochi.test:8888/data/header.png",
     previewURL: "http://mochi.test:8888/data/preview.png",
     iconURL: "http://mochi.test:8888/data/icon.png",
     textcolor: Math.random().toString(),
     accentcolor: Math.random().toString(),
   };
   is(await extension.awaitMessage("onInstalled"), "Bling", "LWT installed");
-  is(await extension.awaitMessage("onDisabled"), "Default", "default disabled");
   is(await extension.awaitMessage("onEnabled"), "Bling", "LWT enabled");
 
   await theme.startup();
   is(await extension.awaitMessage("onInstalled"), "Simple theme test", "webextension theme installed");
   is(await extension.awaitMessage("onDisabled"), "Bling", "LWT disabled");
   // no enabled event when installed.
 
   extension.sendMessage("test");
--- a/toolkit/components/extensions/test/xpcshell/test_ext_management.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_management.js
@@ -29,17 +29,17 @@ add_task(async function test_management_
 
   async function background() {
     browser.test.onMessage.addListener(async (msg, id) => {
       let addon = await browser.management.get(id);
       browser.test.sendMessage("addon", addon);
     });
 
     let addons = await browser.management.getAll();
-    browser.test.assertEq(addons.length, 2, "management.getAll returned two extensions.");
+    browser.test.assertEq(addons.length, 3, "management.getAll returned three add-ons.");
     browser.test.sendMessage("addons", addons);
   }
 
   let extension1 = ExtensionTestUtils.loadExtension({
     manifest: getManifest(id1),
     useAddonManager: "temporary",
   });
 
--- a/toolkit/components/telemetry/tests/unit/xpcshell.ini
+++ b/toolkit/components/telemetry/tests/unit/xpcshell.ini
@@ -6,28 +6,26 @@ firefox-appdir = browser
 support-files =
   ../search/chrome.manifest
   ../search/searchTest.jar
   dictionary.xpi
   experiment.xpi
   engine.xml
   system.xpi
   restartless.xpi
-  theme.xpi
   testUnicodePDB32.dll
   testNoPDB32.dll
   testUnicodePDB64.dll
   testNoPDB64.dll
   !/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
 generated-files =
   dictionary.xpi
   experiment.xpi
   system.xpi
   restartless.xpi
-  theme.xpi
 
 [test_MigratePendingPings.js]
 [test_TelemetryHistograms.js]
 [test_TelemetryStorage.js]
 [test_SubsessionChaining.js]
 tags = addons
 [test_TelemetryEnvironment.js]
 skip-if = os == "android"
--- a/toolkit/locales/en-US/chrome/global/extensions.properties
+++ b/toolkit/locales/en-US/chrome/global/extensions.properties
@@ -32,8 +32,13 @@ saveaspdf.saveasdialog.title = Save As
 
 #LOCALIZATION NOTE (newTabControlled.message2) %S is the icon and name of the extension which updated the New Tab page.
 newTabControlled.message2 = An extension, %S, changed the page you see when you open a new tab.
 newTabControlled.learnMore = Learn more
 
 #LOCALIZATION NOTE (homepageControlled.message) %S is the icon and name of the extension which updated the homepage.
 homepageControlled.message = An extension, %S, changed what you see when you open your homepage and new windows.
 homepageControlled.learnMore = Learn more
+
+# LOCALIZATION NOTE (defaultTheme.name): This is displayed in about:addons -> Appearance
+defaultTheme.name=Default
+defaultTheme.description=The default theme.
+
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -40,16 +40,18 @@ const PREF_WEBEXT_PERM_PROMPTS        = 
 const UPDATE_REQUEST_VERSION          = 2;
 
 const XMLURI_BLOCKLIST                = "http://www.mozilla.org/2006/addons-blocklist";
 
 const KEY_PROFILEDIR                  = "ProfD";
 const KEY_APPDIR                      = "XCurProcD";
 const FILE_BLOCKLIST                  = "blocklist.xml";
 
+const DEFAULT_THEME_ID                = "default-theme@mozilla.org";
+
 const BRANCH_REGEXP                   = /^([^\.]+\.[0-9]+[a-z]*).*/gi;
 const PREF_EM_CHECK_COMPATIBILITY_BASE = "extensions.checkCompatibility";
 var PREF_EM_CHECK_COMPATIBILITY = MOZ_COMPATIBILITY_NIGHTLY ?
                                   PREF_EM_CHECK_COMPATIBILITY_BASE + ".nightly" :
                                   undefined;
 
 const VALID_TYPES_REGEXP = /^[\w\-]+$/;
 
@@ -65,16 +67,17 @@ const URI_XPINSTALL_DIALOG = "chrome://m
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/AsyncShutdown.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   AddonRepository: "resource://gre/modules/addons/AddonRepository.jsm",
   Extension: "resource://gre/modules/Extension.jsm",
   FileUtils: "resource://gre/modules/FileUtils.jsm",
+  LightweightThemeManager: "resource://gre/modules/LightweightThemeManager.jsm",
   PromptUtils: "resource://gre/modules/SharedPromptUtils.jsm",
 });
 
 XPCOMUtils.defineLazyPreferenceGetter(this, "WEBEXT_PERMISSION_PROMPTS",
                                       PREF_WEBEXT_PERM_PROMPTS, false);
 
 // Initialize the WebExtension process script service as early as possible,
 // since it needs to be able to track things like new frameLoader globals that
@@ -833,16 +836,37 @@ var AddonManagerInternal = {
 
       gStartupComplete = true;
       this.recordTimestamp("AMI_startup_end");
     } catch (e) {
       logger.error("startup failed", e);
       AddonManagerPrivate.recordException("AMI", "startup failed", e);
     }
 
+    let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
+    let extensionsBundle = Services.strings.createBundle(
+      "chrome://global/locale/extensions.properties");
+
+    // When running in xpcshell tests, the default theme may already
+    // exist.
+    if (!LightweightThemeManager._builtInThemes.has(DEFAULT_THEME_ID)) {
+      let author = "Mozilla";
+      try {
+        author = brandBundle.GetStringFromName("vendorShortName");
+      } catch (e) {}
+
+      LightweightThemeManager.addBuiltInTheme({
+        id: DEFAULT_THEME_ID,
+        name: extensionsBundle.GetStringFromName("defaultTheme.name"),
+        description: extensionsBundle.GetStringFromName("defaultTheme.description"),
+        iconURL: "chrome://mozapps/content/extensions/default-theme-icon.svg",
+        author,
+      });
+    }
+
     logger.debug("Completed startup sequence");
     this.callManagerListeners("onStartup");
   },
 
   /**
    * Registers a new AddonProvider.
    *
    * @param {string} aProvider -The provider to register
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -7,22 +7,22 @@
 var EXPORTED_SYMBOLS = ["LightweightThemeManager"];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
 /* globals AddonManagerPrivate*/
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 const ID_SUFFIX              = "@personas.mozilla.org";
-const PREF_LWTHEME_TO_SELECT = "extensions.lwThemeToSelect";
 const ADDON_TYPE             = "theme";
 const ADDON_TYPE_WEBEXT      = "webextension-theme";
 
 const URI_EXTENSION_STRINGS  = "chrome://mozapps/locale/extensions/extensions.properties";
 
+const DEFAULT_THEME_ID = "default-theme@mozilla.org";
 const DEFAULT_MAX_USED_THEMES_COUNT = 30;
 
 const MAX_PREVIEW_SECONDS = 30;
 
 const MANDATORY = ["id", "name"];
 const OPTIONAL = ["headerURL", "footerURL", "textcolor", "accentcolor",
                   "iconURL", "previewURL", "author", "description",
                   "homepageURL", "updateURL", "version"];
@@ -115,28 +115,28 @@ var LightweightThemeManager = {
       themes = JSON.parse(_prefs.getStringPref("usedThemes"));
     } catch (e) { }
 
     themes.push(...this._builtInThemes.values());
     return themes;
   },
 
   get currentTheme() {
-    let selectedThemeID = _prefs.getCharPref("selectedThemeID", "");
+    let selectedThemeID = _prefs.getStringPref("selectedThemeID", DEFAULT_THEME_ID);
 
     let data = null;
     if (selectedThemeID) {
       data = this.getUsedTheme(selectedThemeID);
     }
     return data;
   },
 
   get currentThemeForDisplay() {
     var data = this.currentTheme;
-    if (!data && _fallbackThemeData)
+    if ((!data || data.id == DEFAULT_THEME_ID) && _fallbackThemeData)
       data = _fallbackThemeData;
 
     if (data && PERSIST_ENABLED) {
       for (let key in PERSIST_FILES) {
         try {
           if (data[key] && _prefs.getBoolPref("persisted." + key))
             data[key] = _getLocalImageURI(PERSIST_FILES[key]).spec
                         + "?" + data.id + ";" + _version(data);
@@ -184,17 +184,17 @@ var LightweightThemeManager = {
 
   addBuiltInTheme(theme) {
     if (!theme || !theme.id || this.usedThemes.some(t => t.id == theme.id)) {
       throw new Error("Trying to add invalid builtIn theme");
     }
 
     this._builtInThemes.set(theme.id, theme);
 
-    if (_prefs.getCharPref("selectedThemeID") == theme.id) {
+    if (_prefs.getStringPref("selectedThemeID", DEFAULT_THEME_ID) == theme.id) {
       this.currentTheme = theme;
     }
   },
 
   forgetBuiltInTheme(id) {
     if (!this._builtInThemes.has(id)) {
       let currentTheme = this.currentTheme;
       if (currentTheme && currentTheme.id == id) {
@@ -318,25 +318,16 @@ var LightweightThemeManager = {
     Services.obs.notifyObservers(null, "lightweight-theme-changed");
   },
 
   /**
    * Starts the Addons provider and enables the new lightweight theme if
    * necessary.
    */
   startup() {
-    if (Services.prefs.prefHasUserValue(PREF_LWTHEME_TO_SELECT)) {
-      let id = Services.prefs.getCharPref(PREF_LWTHEME_TO_SELECT);
-      if (id)
-        this.themeChanged(this.getUsedTheme(id));
-      else
-        this.themeChanged(null);
-      Services.prefs.clearUserPref(PREF_LWTHEME_TO_SELECT);
-    }
-
     _prefs.addObserver("", _prefObserver);
   },
 
   /**
    * Shuts down the provider.
    */
   shutdown() {
     _prefs.removeObserver("", _prefObserver);
@@ -345,78 +336,54 @@ var LightweightThemeManager = {
   /**
    * Called when a new add-on has been enabled when only one add-on of that type
    * can be enabled.
    *
    * @param  aId
    *         The ID of the newly enabled add-on
    * @param  aType
    *         The type of the newly enabled add-on
-   * @param  aPendingRestart
-   *         true if the newly enabled add-on will only become enabled after a
-   *         restart
    */
-  addonChanged(aId, aType, aPendingRestart) {
+  addonChanged(aId, aType) {
     if (aType != ADDON_TYPE && aType != ADDON_TYPE_WEBEXT)
       return;
 
     let id = _getInternalID(aId);
     let current = this.currentTheme;
 
-    try {
-      let next = Services.prefs.getCharPref(PREF_LWTHEME_TO_SELECT);
-      if (id == next && aPendingRestart)
-        return;
-
-      Services.prefs.clearUserPref(PREF_LWTHEME_TO_SELECT);
-      if (next) {
-        AddonManagerPrivate.callAddonListeners("onOperationCancelled",
-                                               new AddonWrapper(this.getUsedTheme(next)));
-      } else if (id == current.id) {
-        AddonManagerPrivate.callAddonListeners("onOperationCancelled",
-                                               new AddonWrapper(current));
-        return;
-      }
-    } catch (e) {
+    if (current && id == current.id) {
+      AddonManagerPrivate.callAddonListeners("onOperationCancelled",
+                                             new AddonWrapper(current));
+      return;
     }
 
     if (current) {
-      if (current.id == id)
+      if (current.id == id || (!aId && current.id == DEFAULT_THEME_ID))
         return;
       _themeIDBeingDisabled = current.id;
       let wrapper = new AddonWrapper(current);
-      if (aPendingRestart) {
-        Services.prefs.setCharPref(PREF_LWTHEME_TO_SELECT, "");
-        AddonManagerPrivate.callAddonListeners("onDisabling", wrapper, true);
-      } else {
-        AddonManagerPrivate.callAddonListeners("onDisabling", wrapper, false);
-        this.themeChanged(null);
-        AddonManagerPrivate.callAddonListeners("onDisabled", wrapper);
-      }
+
+      AddonManagerPrivate.callAddonListeners("onDisabling", wrapper, false);
+      this.themeChanged(null);
+      AddonManagerPrivate.callAddonListeners("onDisabled", wrapper);
       _themeIDBeingDisabled = null;
     }
 
     if (id) {
       let theme = this.getUsedTheme(id);
       // WebExtension themes have an ID, but no LWT wrapper, so bail out here.
       if (!theme)
         return;
       _themeIDBeingEnabled = id;
       let wrapper = new AddonWrapper(theme);
-      if (aPendingRestart) {
-        AddonManagerPrivate.callAddonListeners("onEnabling", wrapper, true);
-        Services.prefs.setCharPref(PREF_LWTHEME_TO_SELECT, id);
 
-        // Flush the preferences to disk so they survive any crash
-        Services.prefs.savePrefFile(null);
-      } else {
-        AddonManagerPrivate.callAddonListeners("onEnabling", wrapper, false);
-        this.themeChanged(theme);
-        AddonManagerPrivate.callAddonListeners("onEnabled", wrapper);
-      }
+      AddonManagerPrivate.callAddonListeners("onEnabling", wrapper, false);
+      this.themeChanged(theme);
+      AddonManagerPrivate.callAddonListeners("onEnabled", wrapper);
+
       _themeIDBeingEnabled = null;
     }
   },
 
   /**
    * Called to get an Addon with a particular ID.
    *
    * @param  aId
@@ -459,17 +426,17 @@ let themeFor = wrapper => wrapperMap.get
  * consumers of the AddonManager API.
  */
 function AddonWrapper(aTheme) {
   wrapperMap.set(this, aTheme);
 }
 
 AddonWrapper.prototype = {
   get id() {
-    return themeFor(this).id + ID_SUFFIX;
+    return _getExternalID(themeFor(this).id);
   },
 
   get type() {
     return ADDON_TYPE;
   },
 
   get isActive() {
     let current = LightweightThemeManager.currentTheme;
@@ -517,35 +484,30 @@ AddonWrapper.prototype = {
   get permissions() {
     let permissions = 0;
 
     // Do not allow uninstall of builtIn themes.
     if (!LightweightThemeManager._builtInThemes.has(themeFor(this).id))
       permissions = AddonManager.PERM_CAN_UNINSTALL;
     if (this.userDisabled)
       permissions |= AddonManager.PERM_CAN_ENABLE;
-    else
+    else if (themeFor(this).id != DEFAULT_THEME_ID)
       permissions |= AddonManager.PERM_CAN_DISABLE;
     return permissions;
   },
 
   get userDisabled() {
     let id = themeFor(this).id;
     if (_themeIDBeingEnabled == id)
       return false;
     if (_themeIDBeingDisabled == id)
       return true;
 
-    try {
-      let toSelect = Services.prefs.getCharPref(PREF_LWTHEME_TO_SELECT);
-      return id != toSelect;
-    } catch (e) {
-      let current = LightweightThemeManager.currentTheme;
-      return !current || current.id != id;
-    }
+    let current = LightweightThemeManager.currentTheme;
+    return !current || current.id != id;
   },
 
   set userDisabled(val) {
     if (val == this.userDisabled)
       return val;
 
     if (val)
       LightweightThemeManager.currentTheme = null;
@@ -633,22 +595,30 @@ AddonWrapper.prototype = {
  *          The ID to be converted
  *
  * @return  the lightweight theme ID or null if the ID was not for a lightweight
  *          theme.
  */
 function _getInternalID(id) {
   if (!id)
     return null;
+  if (id == DEFAULT_THEME_ID)
+    return id;
   let len = id.length - ID_SUFFIX.length;
   if (len > 0 && id.substring(len) == ID_SUFFIX)
     return id.substring(0, len);
   return null;
 }
 
+function _getExternalID(id) {
+  if (id == DEFAULT_THEME_ID)
+    return id;
+  return id + ID_SUFFIX;
+}
+
 function _setCurrentTheme(aData, aLocal) {
   aData = _sanitizeTheme(aData, null, aLocal);
 
   let cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
   cancel.data = false;
   Services.obs.notifyObservers(cancel, "lightweight-theme-change-requested",
                                JSON.stringify(aData));
 
@@ -686,17 +656,17 @@ function _setCurrentTheme(aData, aLocal)
     if (isInstall)
       AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
   }
 
   if (cancel.data)
     return null;
 
   if (notify) {
-    AddonManagerPrivate.notifyAddonChanged(aData ? aData.id + ID_SUFFIX : null,
+    AddonManagerPrivate.notifyAddonChanged(aData ? _getExternalID(aData.id) : null,
                                            ADDON_TYPE, false);
   }
 
   return LightweightThemeManager.currentTheme;
 }
 
 function _sanitizeTheme(aData, aBaseURI, aLocal) {
   if (!aData || typeof aData != "object")
rename from browser/base/content/default-theme-icon.svg
rename to toolkit/mozapps/extensions/content/default-theme-icon.svg
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -240,17 +240,18 @@ function isLegacyExtension(addon) {
     legacy = true;
   }
   if (addon.type == "theme") {
     // The logic here is kind of clunky but we want to mark complete
     // themes as legacy.  There's no explicit flag for complete
     // themes so explicitly check for new style themes (for which
     // isWebExtension is true) or lightweight themes (which have
     // ids that end with @personas.mozilla.org)
-    legacy = !(addon.isWebExtension || addon.id.endsWith("@personas.mozilla.org"));
+    legacy = !(addon.isWebExtension || addon.id.endsWith("@personas.mozilla.org") ||
+               addon.id == "default-theme@mozilla.org");
   }
 
   if (legacy && (addon.hidden || addon.signedState == AddonManager.SIGNEDSTATE_PRIVILEGED)) {
     legacy = false;
   }
   // Exceptions that can slip through above: the default theme plus
   // test pilot addons until we get SIGNEDSTATE_PRIVILEGED deployed.
   if (legacy && legacyWarningExceptions.includes(addon.id)) {
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
@@ -954,16 +954,18 @@ var AddonTestUtils = {
    */
   writeFilesToZip(zipFile, files, flags = 0) {
     if (typeof zipFile == "string")
       zipFile = nsFile(zipFile);
 
     var zipW = ZipWriter(zipFile, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | flags);
 
     for (let [path, data] of Object.entries(files)) {
+      if (typeof data === "object" && ChromeUtils.getClassName(data) === "Object")
+        data = JSON.stringify(data);
       if (!(data instanceof ArrayBuffer))
         data = new TextEncoder("utf-8").encode(data).buffer;
 
       let stream = ArrayBufferInputStream(data, 0, data.byteLength);
 
       // Note these files are being created in the XPI archive with date "0" which is 1970-01-01.
       zipW.addEntryStream(path, 0, Ci.nsIZipWriter.COMPRESSION_NONE,
                           stream, false);
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -66,18 +66,16 @@ XPCOMUtils.defineLazyServiceGetters(this
 
 ChromeUtils.defineModuleGetter(this, "XPIInternal",
                                "resource://gre/modules/addons/XPIProvider.jsm");
 ChromeUtils.defineModuleGetter(this, "XPIProvider",
                                "resource://gre/modules/addons/XPIProvider.jsm");
 
 const PREF_ALLOW_NON_RESTARTLESS      = "extensions.legacy.non-restartless.enabled";
 
-const DEFAULT_SKIN = "classic/1.0";
-
 /* globals AddonInternal, BOOTSTRAP_REASONS, KEY_APP_SYSTEM_ADDONS, KEY_APP_SYSTEM_DEFAULTS, KEY_APP_TEMPORARY, TEMPORARY_ADDON_SUFFIX, SIGNED_TYPES, TOOLKIT_ID, XPIDatabase, XPIStates, getExternalType, isTheme, isUsableAddon, isWebExtension, mustSign, recordAddonTelemetry */
 const XPI_INTERNAL_SYMBOLS = [
   "AddonInternal",
   "BOOTSTRAP_REASONS",
   "KEY_APP_SYSTEM_ADDONS",
   "KEY_APP_SYSTEM_DEFAULTS",
   "KEY_APP_TEMPORARY",
   "SIGNED_TYPES",
@@ -153,24 +151,23 @@ const PROP_METADATA      = ["id", "versi
                             "optionsURL", "optionsType", "aboutURL",
                             "iconURL", "icon64URL"];
 const PROP_LOCALE_SINGLE = ["name", "description", "creator", "homepageURL"];
 const PROP_LOCALE_MULTI  = ["developers", "translators", "contributors"];
 const PROP_TARGETAPP     = ["id", "minVersion", "maxVersion"];
 
 // Map new string type identifiers to old style nsIUpdateItem types.
 // Retired values:
-// 8 = locale
 // 32 = multipackage xpi file
 // 8 = locale
 // 256 = apiextension
 // 128 = experiment
+// theme = 4
 const TYPES = {
   extension: 2,
-  theme: 4,
   dictionary: 64,
 };
 
 const COMPATIBLE_BY_DEFAULT_TYPES = {
   extension: true,
   dictionary: true,
 };
 
@@ -796,26 +793,17 @@ async function loadManifestFromRDF(aUri,
       platform.abi = targetPlatform.substring(pos + 1);
     } else {
       platform.os = targetPlatform;
     }
 
     addon.targetPlatforms.push(platform);
   }
 
-  // A theme's userDisabled value is true if the theme is not the selected skin
-  // or if there is an active lightweight theme. We ignore whether softblocking
-  // is in effect since it would change the active theme.
-  if (isTheme(addon.type)) {
-    addon.userDisabled = !!LightweightThemeManager.currentTheme ||
-                         addon.internalName != DEFAULT_SKIN;
-  } else {
-    addon.userDisabled = false;
-  }
-
+  addon.userDisabled = false;
   addon.softDisabled = addon.blocklistState == nsIBlocklistService.STATE_SOFTBLOCKED;
   addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;
 
   // icons will be filled by the calling function
   addon.icons = {};
   addon.userPermissions = null;
 
   return addon;
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -82,18 +82,16 @@ const PREF_SYSTEM_ADDON_SET           = 
 const PREF_SYSTEM_ADDON_UPDATE_URL    = "extensions.systemAddon.update.url";
 const PREF_ALLOW_LEGACY               = "extensions.legacy.enabled";
 
 const PREF_EM_MIN_COMPAT_APP_VERSION      = "extensions.minCompatibleAppVersion";
 const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion";
 
 const PREF_EM_LAST_APP_BUILD_ID       = "extensions.lastAppBuildId";
 
-const DEFAULT_SKIN = "classic/1.0";
-
 // Specify a list of valid built-in add-ons to load.
 const BUILT_IN_ADDONS_URI             = "chrome://browser/content/built_in_addons.json";
 
 const OBSOLETE_PREFERENCES = [
   "extensions.bootstrappedAddons",
   "extensions.enabledAddons",
   "extensions.xpiState",
   "extensions.installCache",
@@ -107,47 +105,47 @@ const DIR_STAGE                       = 
 const DIR_TRASH                       = "trash";
 
 const FILE_XPI_STATES                 = "addonStartup.json.lz4";
 const FILE_DATABASE                   = "extensions.json";
 const FILE_RDF_MANIFEST               = "install.rdf";
 const FILE_WEB_MANIFEST               = "manifest.json";
 const FILE_XPI_ADDONS_LIST            = "extensions.ini";
 
-const ADDON_ID_DEFAULT_THEME          = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
-
 const KEY_PROFILEDIR                  = "ProfD";
 const KEY_ADDON_APP_DIR               = "XREAddonAppDir";
 const KEY_APP_DISTRIBUTION            = "XREAppDist";
 const KEY_APP_FEATURES                = "XREAppFeat";
 
 const KEY_APP_PROFILE                 = "app-profile";
 const KEY_APP_SYSTEM_ADDONS           = "app-system-addons";
 const KEY_APP_SYSTEM_DEFAULTS         = "app-system-defaults";
 const KEY_APP_GLOBAL                  = "app-global";
 const KEY_APP_SYSTEM_LOCAL            = "app-system-local";
 const KEY_APP_SYSTEM_SHARE            = "app-system-share";
 const KEY_APP_SYSTEM_USER             = "app-system-user";
 const KEY_APP_TEMPORARY               = "app-temporary";
 
+const DEFAULT_THEME_ID = "default-theme@mozilla.org";
+
 const TEMPORARY_ADDON_SUFFIX = "@temporary-addon";
 
 const STARTUP_MTIME_SCOPES = [KEY_APP_GLOBAL,
                               KEY_APP_SYSTEM_LOCAL,
                               KEY_APP_SYSTEM_SHARE,
                               KEY_APP_SYSTEM_USER];
 
 const NOTIFICATION_FLUSH_PERMISSIONS  = "flush-pending-permissions";
 const XPI_PERMISSION                  = "install";
 
 const TOOLKIT_ID                      = "toolkit@mozilla.org";
 
 const XPI_SIGNATURE_CHECK_PERIOD      = 24 * 60 * 60;
 
-XPCOMUtils.defineConstant(this, "DB_SCHEMA", 24);
+XPCOMUtils.defineConstant(this, "DB_SCHEMA", 25);
 
 const NOTIFICATION_TOOLBOX_CONNECTION_CHANGE      = "toolbox-connection-change";
 
 // Properties that exist in the install manifest
 const PROP_LOCALE_SINGLE = ["name", "description", "creator", "homepageURL"];
 const PROP_LOCALE_MULTI  = ["developers", "translators", "contributors"];
 
 // Properties to cache and reload when an addon installation is pending
@@ -206,17 +204,16 @@ const SIGNED_TYPES = new Set([
   "extension",
   "webextension",
   "webextension-langpack",
   "webextension-theme",
 ]);
 
 const LEGACY_TYPES = new Set([
   "extension",
-  "theme",
 ]);
 
 const ALL_EXTERNAL_TYPES = new Set([
   "dictionary",
   "extension",
   "locale",
   "theme",
 ]);
@@ -284,17 +281,16 @@ function loadLazyObjects() {
     wantGlobalProperties: ["ChromeUtils", "TextDecoder"],
   });
 
   Object.assign(scope, {
     ADDON_SIGNING: AddonSettings.ADDON_SIGNING,
     SIGNED_TYPES,
     BOOTSTRAP_REASONS,
     DB_SCHEMA,
-    DEFAULT_SKIN,
     AddonInternal,
     XPIProvider,
     XPIStates,
     syncLoadManifestFromFile,
     isUsableAddon,
     recordAddonTelemetry,
     flushChromeCaches: XPIInstall.flushChromeCaches,
     descriptorToPath,
@@ -786,19 +782,16 @@ function isDisabledLegacy(addon) {
 /**
  * Calculates whether an add-on should be appDisabled or not.
  *
  * @param  aAddon
  *         The add-on to check
  * @return true if the add-on should not be appDisabled
  */
 function isUsableAddon(aAddon) {
-  if (aAddon.type == "theme")
-    return aAddon.internalName == DEFAULT_SKIN;
-
   if (mustSign(aAddon.type) && !aAddon.isCorrectlySigned) {
     logger.warn(`Add-on ${aAddon.id} is not correctly signed.`);
     if (Services.prefs.getBoolPref(PREF_XPI_SIGNATURES_DEV_ROOT, false)) {
       logger.warn(`Preference ${PREF_XPI_SIGNATURES_DEV_ROOT} is set.`);
     }
     return false;
   }
 
@@ -1196,24 +1189,17 @@ class XPIState {
   syncWithDB(aDBAddon, aUpdated = false) {
     logger.debug("Updating XPIState for " + JSON.stringify(aDBAddon));
     // If the add-on changes from disabled to enabled, we should re-check the modified time.
     // If this is a newly found add-on, it won't have an 'enabled' field but we
     // did a full recursive scan in that case, so we don't need to do it again.
     // We don't use aDBAddon.active here because it's not updated until after restart.
     let mustGetMod = (aDBAddon.visible && !aDBAddon.disabled && !this.enabled);
 
-    // We need to treat XUL themes specially here, since lightweight
-    // themes require the default theme's chrome to be registered even
-    // though we report it as disabled for UI purposes.
-    if (aDBAddon.type == "theme") {
-      this.enabled = aDBAddon.internalName == DEFAULT_SKIN;
-    } else {
-      this.enabled = aDBAddon.visible && !aDBAddon.disabled;
-    }
+    this.enabled = aDBAddon.visible && !aDBAddon.disabled;
 
     this.version = aDBAddon.version;
     this.type = aDBAddon.type;
     if (aDBAddon.startupData) {
       this.startupData = aDBAddon.startupData;
     }
 
     this.bootstrapped = !!aDBAddon.bootstrap;
@@ -2056,19 +2042,16 @@ var XPIProvider = {
         // effect
         Services.obs.notifyObservers(null, "chrome-flush-skin-caches");
         Services.obs.notifyObservers(null, "chrome-flush-caches");
       }
 
       if (AppConstants.MOZ_CRASHREPORTER) {
         // Annotate the crash report with relevant add-on information.
         try {
-          Services.appinfo.annotateCrashReport("Theme", DEFAULT_SKIN);
-        } catch (e) { }
-        try {
           Services.appinfo.annotateCrashReport("EMCheckCompatibility",
                                                AddonManager.checkCompatibility);
         } catch (e) { }
         this.addAddonsToCrashReporter();
       }
 
       try {
         AddonManagerPrivate.recordTimestamp("XPI_bootstrap_addons_begin");
@@ -2879,40 +2862,16 @@ var XPIProvider = {
   },
 
   getDependentAddons(aAddon) {
     return Array.from(XPIDatabase.getAddons())
                 .filter(addon => addon.dependencies.includes(aAddon.id));
   },
 
   /**
-   * Returns the add-on state data for the restartful extensions which
-   * should be available in safe mode. In particular, this means the
-   * default theme, and only the default theme.
-   *
-   * @returns {object}
-   */
-  getSafeModeExtensions() {
-    let loc = XPIStates.getLocation(KEY_APP_GLOBAL);
-    let state = loc.get(ADDON_ID_DEFAULT_THEME);
-
-    // Use the default state data for the default theme, but always mark
-    // it enabled, in case another theme is enabled in normal mode.
-    let addonData = state.toJSON();
-    addonData.enabled = true;
-
-    return {
-      [KEY_APP_GLOBAL]: {
-        path: loc.path,
-        addons: { [ADDON_ID_DEFAULT_THEME]: addonData },
-      },
-    };
-  },
-
-  /**
    * Checks for any changes that have occurred since the last time the
    * application was launched.
    *
    * @param  aAppChanged
    *         A tri-state value. Undefined means the current profile was created
    *         for this session, true means the profile already existed but was
    *         last used with an application with a different version number,
    *         false means that the profile was last used by this version of the
@@ -3001,35 +2960,23 @@ var XPIProvider = {
                                                                          aOldAppVersion,
                                                                          aOldPlatformVersion,
                                                                          updateReasons.includes("schemaChanged"));
         } catch (e) {
           logger.error("Failed to process extension changes at startup", e);
         }
       }
 
-      if (Services.appinfo.inSafeMode) {
-        aomStartup.initializeExtensions(this.getSafeModeExtensions());
-        logger.debug("Initialized safe mode add-ons");
-        return false;
-      }
-
       // If the application crashed before completing any pending operations then
       // we should perform them now.
       if (extensionListChanged || hasPendingChanges) {
         this._updateActiveAddons();
-
-        // Serialize and deserialize so we get the expected JSON data.
-        let state = JSON.parse(JSON.stringify(XPIStates));
-        aomStartup.initializeExtensions(state);
         return true;
       }
 
-      aomStartup.initializeExtensions(XPIStates.initialStateData);
-
       logger.debug("No changes found");
     } catch (e) {
       logger.error("Error during startup file checks", e);
     }
 
     return false;
   },
 
@@ -3565,24 +3512,31 @@ var XPIProvider = {
    * @param  aType
    *         The type of the newly enabled add-on
    */
   addonChanged(aId, aType) {
     // We only care about themes in this provider
     if (!isTheme(aType))
       return;
 
-    let addons = XPIDatabase.getAddonsByType("theme", "webextension-theme");
+    let addons = XPIDatabase.getAddonsByType("webextension-theme");
     for (let theme of addons) {
-      if (isWebExtension(theme.type) && theme.visible && theme.id != aId)
-        this.updateAddonDisabledState(theme, true, undefined);
-    }
-
-    let defaultTheme = XPIDatabase.getVisibleAddonForInternalName(DEFAULT_SKIN);
-    this.updateAddonDisabledState(defaultTheme, aId && aId != defaultTheme.id);
+      if (theme.visible && theme.id != aId)
+        this.updateAddonDisabledState(theme, true, undefined, true);
+    }
+
+    if (!aId && (!LightweightThemeManager.currentTheme ||
+                 LightweightThemeManager.currentTheme !== DEFAULT_THEME_ID)) {
+      let theme = LightweightThemeManager.getUsedTheme(DEFAULT_THEME_ID);
+      // This can only ever be null in tests.
+      // This can all go away once lightweight themes are gone.
+      if (theme) {
+        LightweightThemeManager.currentTheme = theme;
+      }
+    }
   },
 
   /**
    * Update the appDisabled property for all add-ons.
    */
   updateAddonAppDisabledStates() {
     let addons = XPIDatabase.getAddons();
     for (let addon of addons) {
@@ -3909,23 +3863,26 @@ var XPIProvider = {
    * @param  aAddon
    *         The DBAddonInternal to update
    * @param  aUserDisabled
    *         Value for the userDisabled property. If undefined the value will
    *         not change
    * @param  aSoftDisabled
    *         Value for the softDisabled property. If undefined the value will
    *         not change. If true this will force userDisabled to be true
+   * @param {boolean} aBecauseSelecting
+   *        True if we're disabling this add-on because we're selecting
+   *        another.
    * @return a tri-state indicating the action taken for the add-on:
    *           - undefined: The add-on did not change state
    *           - true: The add-on because disabled
    *           - false: The add-on became enabled
    * @throws if addon is not a DBAddonInternal
    */
-  updateAddonDisabledState(aAddon, aUserDisabled, aSoftDisabled) {
+  updateAddonDisabledState(aAddon, aUserDisabled, aSoftDisabled, aBecauseSelecting) {
     if (!(aAddon.inDatabase))
       throw new Error("Can only update addon states for installed addons.");
     if (aUserDisabled !== undefined && aSoftDisabled !== undefined) {
       throw new Error("Cannot change userDisabled and softDisabled at the " +
                       "same time");
     }
 
     if (aUserDisabled === undefined) {
@@ -4011,22 +3968,26 @@ var XPIProvider = {
           this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "startup",
                                    BOOTSTRAP_REASONS.ADDON_ENABLE);
         }
         AddonManagerPrivate.callAddonListeners("onEnabled", wrapper);
       }
     }
 
     // Notify any other providers that a new theme has been enabled
-    if (isTheme(aAddon.type) && !isDisabled) {
-      AddonManagerPrivate.notifyAddonChanged(aAddon.id, aAddon.type);
-
-      if (xpiState) {
-        xpiState.syncWithDB(aAddon);
-        XPIStates.save();
+    if (isTheme(aAddon.type)) {
+      if (!isDisabled) {
+        AddonManagerPrivate.notifyAddonChanged(aAddon.id, aAddon.type);
+
+        if (xpiState) {
+          xpiState.syncWithDB(aAddon);
+          XPIStates.save();
+        }
+      } else if (isDisabled && !aBecauseSelecting) {
+        AddonManagerPrivate.notifyAddonChanged(null, "theme");
       }
     }
 
     return isDisabled;
   },
 
   /**
    * Uninstalls an add-on, immediately if possible or marks it as pending
@@ -4763,18 +4724,17 @@ AddonWrapper.prototype = {
       if (this.hasResource("icon.png")) {
         icons[32] = icons[48] = this.getResourceURI("icon.png").spec;
       }
       if (this.hasResource("icon64.png")) {
         icons[64] = this.getResourceURI("icon64.png").spec;
       }
     }
 
-    let canUseIconURLs = this.isActive ||
-      (addon.type == "theme" && addon.internalName == DEFAULT_SKIN);
+    let canUseIconURLs = this.isActive;
     if (canUseIconURLs && addon.iconURL) {
       icons[32] = addon.iconURL;
       icons[48] = addon.iconURL;
     }
 
     if (canUseIconURLs && addon.icon64URL) {
       icons[64] = addon.icon64URL;
     }
@@ -4926,32 +4886,22 @@ AddonWrapper.prototype = {
   },
   set userDisabled(val) {
     let addon = addonFor(this);
     if (val == this.userDisabled) {
       return val;
     }
 
     if (addon.inDatabase) {
-      let theme = isTheme(addon.type);
-      if (theme && val) {
-        if (addon.internalName == DEFAULT_SKIN)
-          throw new Error("Cannot disable the default theme");
-
-        let defaultTheme = XPIDatabase.getVisibleAddonForInternalName(DEFAULT_SKIN);
-        XPIProvider.updateAddonDisabledState(defaultTheme, false);
+      // hidden and system add-ons should not be user disabled,
+      // as there is no UI to re-enable them.
+      if (this.hidden) {
+        throw new Error(`Cannot disable hidden add-on ${addon.id}`);
       }
-      if (!(theme && val) || isWebExtension(addon.type)) {
-        // hidden and system add-ons should not be user disasbled,
-        // as there is no UI to re-enable them.
-        if (this.hidden) {
-          throw new Error(`Cannot disable hidden add-on ${addon.id}`);
-        }
-        XPIProvider.updateAddonDisabledState(addon, val);
-      }
+      XPIProvider.updateAddonDisabledState(addon, val);
     } else {
       addon.userDisabled = val;
       // When enabling remove the softDisabled flag
       if (!val)
         addon.softDisabled = false;
     }
 
     return val;
@@ -4960,18 +4910,16 @@ AddonWrapper.prototype = {
   set softDisabled(val) {
     let addon = addonFor(this);
     if (val == addon.softDisabled)
       return val;
 
     if (addon.inDatabase) {
       // When softDisabling a theme just enable the active theme
       if (isTheme(addon.type) && val && !addon.userDisabled) {
-        if (addon.internalName == DEFAULT_SKIN)
-          throw new Error("Cannot disable the default theme");
         if (isWebExtension(addon.type))
           XPIProvider.updateAddonDisabledState(addon, undefined, val);
       } else {
         XPIProvider.updateAddonDisabledState(addon, undefined, val);
       }
     } else if (!addon.userDisabled) {
       // Only set softDisabled if not already disabled
       addon.softDisabled = val;
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -3,17 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 // These are injected from XPIProvider.jsm
 /* globals ADDON_SIGNING, SIGNED_TYPES, BOOTSTRAP_REASONS, DB_SCHEMA,
           AddonInternal, XPIProvider, XPIStates, syncLoadManifestFromFile,
           isUsableAddon, recordAddonTelemetry,
-          flushChromeCaches, descriptorToPath, DEFAULT_SKIN */
+          flushChromeCaches, descriptorToPath */
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   AddonManager: "resource://gre/modules/AddonManager.jsm",
   AddonManagerPrivate: "resource://gre/modules/AddonManager.jsm",
   AddonRepository: "resource://gre/modules/addons/AddonRepository.jsm",
   DeferredTask: "resource://gre/modules/DeferredTask.jsm",
@@ -43,17 +43,17 @@ const PREF_EM_AUTO_DISABLED_SCOPES    = 
 
 const KEY_APP_SYSTEM_ADDONS           = "app-system-addons";
 const KEY_APP_SYSTEM_DEFAULTS         = "app-system-defaults";
 const KEY_APP_GLOBAL                  = "app-global";
 const KEY_APP_TEMPORARY               = "app-temporary";
 
 // Properties to save in JSON file
 const PROP_JSON_FIELDS = ["id", "syncGUID", "location", "version", "type",
-                          "internalName", "updateURL", "optionsURL",
+                          "updateURL", "optionsURL",
                           "optionsType", "optionsBrowserStyle", "aboutURL",
                           "defaultLocale", "visible", "active", "userDisabled",
                           "appDisabled", "pendingUninstall", "installDate",
                           "updateDate", "applyBackgroundUpdates", "bootstrap", "path",
                           "skinnable", "size", "sourceURI", "releaseNotesURI",
                           "softDisabled", "foreignInstall",
                           "strictCompatibility", "locales", "targetApplications",
                           "targetPlatforms", "signedState",
@@ -707,38 +707,16 @@ this.XPIDatabase = {
       AddonManagerPrivate.recordSimpleMeasure("XPIDB_lateOpen_byType", XPIProvider.runPhase);
       this.syncLoadDB(true);
     }
 
     return _filterDB(this.addonDB, aAddon => aTypes.includes(aAddon.type));
   },
 
   /**
-   * Synchronously gets an add-on with a particular internalName.
-   *
-   * @param  aInternalName
-   *         The internalName of the add-on to retrieve
-   * @return a DBAddonInternal
-   */
-  getVisibleAddonForInternalName(aInternalName) {
-    if (!this.addonDB) {
-      // This may be called when the DB hasn't otherwise been loaded
-      logger.warn(`Synchronous load of XPI database due to ` +
-                  `getVisibleAddonForInternalName. Stack: ${Error().stack}`);
-      AddonManagerPrivate.recordSimpleMeasure("XPIDB_lateOpen_forInternalName",
-          XPIProvider.runPhase);
-      this.syncLoadDB(true);
-    }
-
-    return _findAddon(this.addonDB,
-                      aAddon => aAddon.visible &&
-                                (aAddon.internalName == aInternalName));
-  },
-
-  /**
    * Asynchronously gets all add-ons with pending operations.
    *
    * @param  aTypes
    *         The types of add-ons to retrieve or null to get all types
    */
   getVisibleAddonsWithPendingOperations(aTypes) {
     return this.getAddonList(
         aAddon => (aAddon.visible &&
@@ -1090,20 +1068,16 @@ this.XPIDatabaseReconcile = {
     // foreign and should default to enabled.
     aNewAddon.foreignInstall = isDetectedInstall &&
                                aInstallLocation.name != KEY_APP_SYSTEM_ADDONS &&
                                aInstallLocation.name != KEY_APP_SYSTEM_DEFAULTS;
 
     // appDisabled depends on whether the add-on is a foreignInstall so update
     aNewAddon.appDisabled = !isUsableAddon(aNewAddon);
 
-    // The default theme is never a foreign install
-    if (aNewAddon.type == "theme" && aNewAddon.internalName == DEFAULT_SKIN)
-      aNewAddon.foreignInstall = false;
-
     if (isDetectedInstall && aNewAddon.foreignInstall) {
       // If the add-on is a foreign install and is in a scope where add-ons
       // that were dropped in should default to disabled then disable it
       let disablingScopes = Services.prefs.getIntPref(PREF_EM_AUTO_DISABLED_SCOPES, 0);
       if (aInstallLocation.scope & disablingScopes) {
         logger.warn("Disabling foreign installed add-on " + aNewAddon.id + " in "
             + aInstallLocation.name);
         aNewAddon.userDisabled = true;
@@ -1455,21 +1429,17 @@ this.XPIDatabaseReconcile = {
       if (!previousAddon) {
         // If we had a manifest for this add-on it was a staged install and
         // so wasn't something recovered from a corrupt database
         let wasStaged = !!loadedManifest(currentAddon._installLocation, id);
 
         // We might be recovering from a corrupt database, if so use the
         // list of known active add-ons to update the new add-on
         if (!wasStaged && XPIDatabase.activeBundles) {
-          // For themes we know which is active by the current skin setting
-          if (currentAddon.type == "theme")
-            isActive = currentAddon.internalName == DEFAULT_SKIN;
-          else
-            isActive = XPIDatabase.activeBundles.includes(currentAddon.path);
+          isActive = XPIDatabase.activeBundles.includes(currentAddon.path);
 
           if (currentAddon.type == "webextension-theme")
             currentAddon.userDisabled = !isActive;
 
           // If the add-on wasn't active and it isn't already disabled in some way
           // then it was probably either softDisabled or userDisabled
           if (!isActive && !currentAddon.disabled) {
             // If the add-on is softblocked then assume it is softDisabled
--- a/toolkit/mozapps/extensions/jar.mn
+++ b/toolkit/mozapps/extensions/jar.mn
@@ -17,13 +17,14 @@ toolkit.jar:
   content/mozapps/extensions/update.html                        (content/update.html)
   content/mozapps/extensions/update.js                          (content/update.js)
   content/mozapps/extensions/update.css                         (content/update.css)
   content/mozapps/extensions/eula.xul                           (content/eula.xul)
   content/mozapps/extensions/eula.js                            (content/eula.js)
   content/mozapps/extensions/pluginPrefs.xul                    (content/pluginPrefs.xul)
   content/mozapps/extensions/pluginPrefs.js                     (content/pluginPrefs.js)
   content/mozapps/extensions/OpenH264-license.txt               (content/OpenH264-license.txt)
+  content/mozapps/extensions/default-theme-icon.svg             (content/default-theme-icon.svg)
 #endif
   content/mozapps/xpinstall/xpinstallConfirm.xul                (content/xpinstallConfirm.xul)
   content/mozapps/xpinstall/xpinstallConfirm.js                 (content/xpinstallConfirm.js)
   content/mozapps/xpinstall/xpinstallConfirm.css                (content/xpinstallConfirm.css)
   content/mozapps/xpinstall/xpinstallItem.xml                   (content/xpinstallItem.xml)
--- a/toolkit/mozapps/extensions/test/browser/browser.ini
+++ b/toolkit/mozapps/extensions/test/browser/browser.ini
@@ -18,17 +18,16 @@ support-files =
   webapi_checkavailable.html
   webapi_checkchromeframe.xul
   webapi_checkframed.html
   webapi_checknavigatedwindow.html
   !/toolkit/mozapps/extensions/test/xpinstall/corrupt.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html
   !/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi
-  !/toolkit/mozapps/extensions/test/xpinstall/theme.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/amosigned-restart-required.xpi
 
 [browser_CTP_plugins.js]
 tags = blocklist
 skip-if = buildapp == 'mulet'
 [browser_bug523784.js]
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -1105,17 +1105,17 @@ function check_test_completed(aArgs) {
 
   return gNext.apply(null, aArgs);
 }
 
 // Verifies that all the expected events for all add-ons were seen
 function ensure_test_completed() {
   for (let i in gExpectedEvents) {
     if (gExpectedEvents[i].length > 0)
-      do_throw("Didn't see all the expected events for " + i);
+      do_throw(`Didn't see all the expected events for ${i}: Still expecting ${gExpectedEvents[i].map(([k]) => k)}`);
   }
   gExpectedEvents = {};
   if (gExpectedInstalls)
     Assert.equal(gExpectedInstalls.length, 0);
 }
 
 /**
  * A helper method to install an array of AddonInstall to completion and then
--- a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js
@@ -43,50 +43,47 @@ const ADDONS = [
 
       targetApplications: [{
         id: "xpcshell@tests.mozilla.org",
         minVersion: "1",
         maxVersion: "1"}],
     },
   },
   {
-    "install.rdf": {
-      id: "test_AddonRepository_2@tests.mozilla.org",
-      type: 4,
-      internalName: "test2/1.0",
+    "manifest.json": {
+      manifest_version: 2,
+      name: "XPI Add-on 2",
       version: "1.2",
-      bootstrap: true,
-      name: "XPI Add-on 2",
-
-      targetApplications: [{
-        id: "xpcshell@tests.mozilla.org",
-        minVersion: "1",
-        maxVersion: "1"}],
+      applications: {
+        gecko: {
+          id: "test_AddonRepository_2@tests.mozilla.org",
+        },
+      },
+      theme: {},
     },
   },
   {
-    "install.rdf": {
-      id: "test_AddonRepository_3@tests.mozilla.org",
-      type: "4",
-      internalName: "test3/1.0",
+    "manifest.json": {
+      manifest_version: 2,
+      name: "XPI Add-on 3",
       version: "1.3",
-      bootstrap: true,
-      name: "XPI Add-on 3",
-
-      targetApplications: [{
-        id: "xpcshell@tests.mozilla.org",
-        minVersion: "1",
-        maxVersion: "1"}],
+      applications: {
+        gecko: {
+          id: "test_AddonRepository_3@tests.mozilla.org",
+        },
+      },
+      theme: {},
+      icons: {32: "icon.png"},
     },
     "icon.png": "",
     "preview.png": "",
   },
 ];
 
-const ADDON_IDS = ADDONS.map(addon => addon["install.rdf"].id);
+const ADDON_IDS = ADDONS.map(addon => addon["install.rdf"] ? addon["install.rdf"].id : addon["manifest.json"].applications.gecko.id);
 const ADDON_FILES = ADDONS.map(addon => AddonTestUtils.createTempXPIFile(addon));
 
 const PREF_ADDON0_CACHE_ENABLED = "extensions." + ADDON_IDS[0] + ".getAddons.cache.enabled";
 const PREF_ADDON1_CACHE_ENABLED = "extensions." + ADDON_IDS[1] + ".getAddons.cache.enabled";
 
 // Properties of an individual add-on that should be checked
 // Note: size and updateDate are checked separately
 const ADDON_PROPERTIES = ["id", "type", "name", "version", "creator",
--- a/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js
@@ -1,15 +1,17 @@
 const MANDATORY = ["id", "name"];
 const OPTIONAL = ["headerURL", "footerURL", "textcolor", "accentcolor",
                   "iconURL", "previewURL", "author", "description",
                   "homepageURL", "updateURL", "version"];
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
+const DEFAULT_THEME_ID = "default-theme@mozilla.org";
+
 function dummy(id) {
   return {
     id: id || Math.random().toString(),
     name: Math.random().toString(),
     headerURL: "http://lwttest.invalid/a.png",
     footerURL: "http://lwttest.invalid/b.png",
     textcolor: Math.random().toString(),
     accentcolor: Math.random().toString()
@@ -26,147 +28,147 @@ async function run_test() {
   startupManager();
 
   Services.prefs.setIntPref("lightweightThemes.maxUsedThemes", 8);
 
   let {LightweightThemeManager: ltm} = ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm", {});
 
   Assert.equal(typeof ltm, "object");
   Assert.equal(typeof ltm.usedThemes, "object");
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   ltm.previewTheme(dummy("preview0"));
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   ltm.previewTheme(dummy("preview1"));
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
   ltm.resetPreview();
 
   ltm.currentTheme = dummy("x0");
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.id, "x0");
   Assert.equal(ltm.usedThemes[0].id, "x0");
   Assert.equal(ltm.getUsedTheme("x0").id, "x0");
 
   ltm.previewTheme(dummy("preview0"));
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.id, "x0");
 
   ltm.resetPreview();
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.id, "x0");
 
   ltm.currentTheme = dummy("x1");
-  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.equal(ltm.usedThemes.length, 3);
   Assert.equal(ltm.currentTheme.id, "x1");
   Assert.equal(ltm.usedThemes[1].id, "x0");
 
   ltm.currentTheme = dummy("x2");
-  Assert.equal(ltm.usedThemes.length, 3);
+  Assert.equal(ltm.usedThemes.length, 4);
   Assert.equal(ltm.currentTheme.id, "x2");
   Assert.equal(ltm.usedThemes[1].id, "x1");
   Assert.equal(ltm.usedThemes[2].id, "x0");
 
   ltm.currentTheme = dummy("x3");
   ltm.currentTheme = dummy("x4");
   ltm.currentTheme = dummy("x5");
   ltm.currentTheme = dummy("x6");
   ltm.currentTheme = dummy("x7");
-  Assert.equal(ltm.usedThemes.length, 8);
+  Assert.equal(ltm.usedThemes.length, 9);
   Assert.equal(ltm.currentTheme.id, "x7");
   Assert.equal(ltm.usedThemes[1].id, "x6");
   Assert.equal(ltm.usedThemes[7].id, "x0");
 
   ltm.currentTheme = dummy("x8");
-  Assert.equal(ltm.usedThemes.length, 8);
+  Assert.equal(ltm.usedThemes.length, 9);
   Assert.equal(ltm.currentTheme.id, "x8");
   Assert.equal(ltm.usedThemes[1].id, "x7");
   Assert.equal(ltm.usedThemes[7].id, "x1");
   Assert.equal(ltm.getUsedTheme("x0"), null);
 
   ltm.forgetUsedTheme("nonexistent");
-  Assert.equal(ltm.usedThemes.length, 8);
-  Assert.notEqual(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 9);
+  Assert.notEqual(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   ltm.forgetUsedTheme("x8");
-  Assert.equal(ltm.usedThemes.length, 7);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 8);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
   Assert.equal(ltm.usedThemes[0].id, "x7");
   Assert.equal(ltm.usedThemes[6].id, "x1");
 
   ltm.forgetUsedTheme("x7");
   ltm.forgetUsedTheme("x6");
   ltm.forgetUsedTheme("x5");
   ltm.forgetUsedTheme("x4");
   ltm.forgetUsedTheme("x3");
-  Assert.equal(ltm.usedThemes.length, 2);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 3);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
   Assert.equal(ltm.usedThemes[0].id, "x2");
   Assert.equal(ltm.usedThemes[1].id, "x1");
 
   ltm.currentTheme = dummy("x1");
-  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.equal(ltm.usedThemes.length, 3);
   Assert.equal(ltm.currentTheme.id, "x1");
   Assert.equal(ltm.usedThemes[0].id, "x1");
   Assert.equal(ltm.usedThemes[1].id, "x2");
 
   ltm.currentTheme = dummy("x2");
-  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.equal(ltm.usedThemes.length, 3);
   Assert.equal(ltm.currentTheme.id, "x2");
   Assert.equal(ltm.usedThemes[0].id, "x2");
   Assert.equal(ltm.usedThemes[1].id, "x1");
 
   ltm.currentTheme = ltm.getUsedTheme("x1");
-  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.equal(ltm.usedThemes.length, 3);
   Assert.equal(ltm.currentTheme.id, "x1");
   Assert.equal(ltm.usedThemes[0].id, "x1");
   Assert.equal(ltm.usedThemes[1].id, "x2");
 
   ltm.forgetUsedTheme("x1");
   ltm.forgetUsedTheme("x2");
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   // Use chinese name to test utf-8, for bug #541943
   var chineseTheme = dummy("chinese0");
   chineseTheme.name = "笢恅0";
   chineseTheme.description = "笢恅1";
   ltm.currentTheme = chineseTheme;
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.name, "笢恅0");
   Assert.equal(ltm.currentTheme.description, "笢恅1");
   Assert.equal(ltm.usedThemes[0].name, "笢恅0");
   Assert.equal(ltm.usedThemes[0].description, "笢恅1");
   Assert.equal(ltm.getUsedTheme("chinese0").name, "笢恅0");
   Assert.equal(ltm.getUsedTheme("chinese0").description, "笢恅1");
 
   // This name used to break the usedTheme JSON causing all LWTs to be lost
   var chineseTheme1 = dummy("chinese1");
   chineseTheme1.name = "眵昜湮桵蔗坌~郔乾";
   chineseTheme1.description = "眵昜湮桵蔗坌~郔乾";
   ltm.currentTheme = chineseTheme1;
-  Assert.notEqual(ltm.currentTheme, null);
-  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.notEqual(ltm.currentTheme.id, DEFAULT_THEME_ID);
+  Assert.equal(ltm.usedThemes.length, 3);
   Assert.equal(ltm.currentTheme.name, "眵昜湮桵蔗坌~郔乾");
   Assert.equal(ltm.currentTheme.description, "眵昜湮桵蔗坌~郔乾");
   Assert.equal(ltm.usedThemes[1].name, "笢恅0");
   Assert.equal(ltm.usedThemes[1].description, "笢恅1");
   Assert.equal(ltm.usedThemes[0].name, "眵昜湮桵蔗坌~郔乾");
   Assert.equal(ltm.usedThemes[0].description, "眵昜湮桵蔗坌~郔乾");
 
   ltm.forgetUsedTheme("chinese0");
-  Assert.equal(ltm.usedThemes.length, 1);
-  Assert.notEqual(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.notEqual(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   ltm.forgetUsedTheme("chinese1");
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   Assert.equal(ltm.parseTheme("invalid json"), null);
   Assert.equal(ltm.parseTheme('"json string"'), null);
 
   function roundtrip(data, secure) {
     return ltm.parseTheme(JSON.stringify(data),
                           "http" + (secure ? "s" : "") + "://lwttest.invalid/");
   }
@@ -295,142 +297,142 @@ async function run_test() {
   });
 
   roundtripSet(urls(OPTIONAL), function(theme, prop) {
     theme[prop] = "ftp://lwttest.invalid/" + Math.random().toString();
   }, function(after, prop) {
     Assert.equal(typeof after[prop], "undefined");
   });
 
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   data = dummy();
   delete data.name;
   try {
     ltm.currentTheme = data;
     do_throw("Should have rejected a theme with no name");
   } catch (e) {
     // Expected exception
   }
 
   // Sanitize themes with a bad headerURL
   data = dummy();
   data.headerURL = "foo";
   ltm.currentTheme = data;
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.headerURL, undefined);
   ltm.forgetUsedTheme(ltm.currentTheme.id);
-  Assert.equal(ltm.usedThemes.length, 0);
+  Assert.equal(ltm.usedThemes.length, 1);
 
   // Sanitize themes with a non-http(s) headerURL
   data = dummy();
   data.headerURL = "ftp://lwtest.invalid/test.png";
   ltm.currentTheme = data;
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.headerURL, undefined);
   ltm.forgetUsedTheme(ltm.currentTheme.id);
-  Assert.equal(ltm.usedThemes.length, 0);
+  Assert.equal(ltm.usedThemes.length, 1);
 
   // Sanitize themes with a non-http(s) headerURL
   data = dummy();
   data.headerURL = "file:///test.png";
   ltm.currentTheme = data;
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.headerURL, undefined);
   ltm.forgetUsedTheme(ltm.currentTheme.id);
-  Assert.equal(ltm.usedThemes.length, 0);
+  Assert.equal(ltm.usedThemes.length, 1);
 
   data = dummy();
   data.updateURL = "file:///test.json";
   ltm.setLocalTheme(data);
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.updateURL, undefined);
   ltm.forgetUsedTheme(ltm.currentTheme.id);
-  Assert.equal(ltm.usedThemes.length, 0);
+  Assert.equal(ltm.usedThemes.length, 1);
 
   data = dummy();
   data.headerURL = "file:///test.png";
   ltm.setLocalTheme(data);
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.headerURL, "file:///test.png");
   ltm.forgetUsedTheme(ltm.currentTheme.id);
-  Assert.equal(ltm.usedThemes.length, 0);
+  Assert.equal(ltm.usedThemes.length, 1);
 
   data = dummy();
   data.headerURL = "ftp://lwtest.invalid/test.png";
   ltm.setLocalTheme(data);
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   Assert.equal(ltm.currentTheme.updateURL, undefined);
   ltm.forgetUsedTheme(ltm.currentTheme.id);
-  Assert.equal(ltm.usedThemes.length, 0);
+  Assert.equal(ltm.usedThemes.length, 1);
 
   data = dummy();
   delete data.id;
   try {
     ltm.currentTheme = data;
     do_throw("Should have rejected a theme with no ID");
   } catch (e) {
     // Expected exception
   }
 
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   // Force the theme into the prefs anyway
   let themes = [data];
   Services.prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(themes));
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
 
   // This should silently drop the bad theme.
   ltm.currentTheme = dummy();
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   ltm.forgetUsedTheme(ltm.currentTheme.id);
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   // Add one broken and some working.
   themes = [data, dummy("x1"), dummy("x2")];
   Services.prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(themes));
-  Assert.equal(ltm.usedThemes.length, 3);
+  Assert.equal(ltm.usedThemes.length, 4);
 
   // Switching to an existing theme should drop the bad theme.
   ltm.currentTheme = ltm.getUsedTheme("x1");
-  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.equal(ltm.usedThemes.length, 3);
   ltm.forgetUsedTheme("x1");
   ltm.forgetUsedTheme("x2");
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   Services.prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(themes));
-  Assert.equal(ltm.usedThemes.length, 3);
+  Assert.equal(ltm.usedThemes.length, 4);
 
   // Forgetting an existing theme should drop the bad theme.
   ltm.forgetUsedTheme("x1");
-  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.usedThemes.length, 2);
   ltm.forgetUsedTheme("x2");
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   // Test whether a JSON set with setCharPref can be retrieved with usedThemes
   ltm.currentTheme = dummy("x0");
   ltm.currentTheme = dummy("x1");
   Services.prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(ltm.usedThemes));
-  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.equal(ltm.usedThemes.length, 4);
   Assert.equal(ltm.currentTheme.id, "x1");
   Assert.equal(ltm.usedThemes[1].id, "x0");
   Assert.equal(ltm.usedThemes[0].id, "x1");
 
   ltm.forgetUsedTheme("x0");
-  Assert.equal(ltm.usedThemes.length, 1);
-  Assert.notEqual(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.notEqual(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   ltm.forgetUsedTheme("x1");
-  Assert.equal(ltm.usedThemes.length, 0);
-  Assert.equal(ltm.currentTheme, null);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.id, DEFAULT_THEME_ID);
 
   Services.prefs.clearUserPref("lightweightThemes.maxUsedThemes");
 
   ltm.currentTheme = dummy("x1");
   ltm.currentTheme = dummy("x2");
   ltm.currentTheme = dummy("x3");
   ltm.currentTheme = dummy("x4");
   ltm.currentTheme = dummy("x5");
@@ -455,26 +457,26 @@ async function run_test() {
   ltm.currentTheme = dummy("x24");
   ltm.currentTheme = dummy("x25");
   ltm.currentTheme = dummy("x26");
   ltm.currentTheme = dummy("x27");
   ltm.currentTheme = dummy("x28");
   ltm.currentTheme = dummy("x29");
   ltm.currentTheme = dummy("x30");
 
-  Assert.equal(ltm.usedThemes.length, 30);
+  Assert.equal(ltm.usedThemes.length, 31);
 
   ltm.currentTheme = dummy("x31");
 
-  Assert.equal(ltm.usedThemes.length, 30);
+  Assert.equal(ltm.usedThemes.length, 31);
   Assert.equal(ltm.getUsedTheme("x1"), null);
 
   Services.prefs.setIntPref("lightweightThemes.maxUsedThemes", 15);
 
-  Assert.equal(ltm.usedThemes.length, 15);
+  Assert.equal(ltm.usedThemes.length, 16);
 
   Services.prefs.setIntPref("lightweightThemes.maxUsedThemes", 32);
 
   ltm.currentTheme = dummy("x1");
   ltm.currentTheme = dummy("x2");
   ltm.currentTheme = dummy("x3");
   ltm.currentTheme = dummy("x4");
   ltm.currentTheme = dummy("x5");
@@ -487,45 +489,45 @@ async function run_test() {
   ltm.currentTheme = dummy("x12");
   ltm.currentTheme = dummy("x13");
   ltm.currentTheme = dummy("x14");
   ltm.currentTheme = dummy("x15");
   ltm.currentTheme = dummy("x16");
 
   ltm.currentTheme = dummy("x32");
 
-  Assert.equal(ltm.usedThemes.length, 32);
+  Assert.equal(ltm.usedThemes.length, 33);
 
   ltm.currentTheme = dummy("x33");
 
-  Assert.equal(ltm.usedThemes.length, 32);
+  Assert.equal(ltm.usedThemes.length, 33);
 
   Services.prefs.clearUserPref("lightweightThemes.maxUsedThemes");
 
-  Assert.equal(ltm.usedThemes.length, 30);
+  Assert.equal(ltm.usedThemes.length, 31);
 
   let usedThemes = ltm.usedThemes;
   for (let theme of usedThemes) {
     ltm.forgetUsedTheme(theme.id);
   }
 
   // Check builtInTheme functionality for Bug 1094821
   Assert.equal(ltm._builtInThemes.toString(), "[object Map]");
-  Assert.equal([...ltm._builtInThemes.entries()].length, 0);
-  Assert.equal(ltm.usedThemes.length, 0);
+  Assert.equal([...ltm._builtInThemes.entries()].length, 1);
+  Assert.equal(ltm.usedThemes.length, 1);
 
   ltm.addBuiltInTheme(dummy("builtInTheme0"));
-  Assert.equal([...ltm._builtInThemes].length, 1);
-  Assert.equal(ltm.usedThemes.length, 1);
-  Assert.equal(ltm.usedThemes[0].id, "builtInTheme0");
+  Assert.equal([...ltm._builtInThemes].length, 2);
+  Assert.equal(ltm.usedThemes.length, 2);
+  Assert.equal(ltm.usedThemes[1].id, "builtInTheme0");
 
   ltm.addBuiltInTheme(dummy("builtInTheme1"));
-  Assert.equal([...ltm._builtInThemes].length, 2);
-  Assert.equal(ltm.usedThemes.length, 2);
-  Assert.equal(ltm.usedThemes[1].id, "builtInTheme1");
+  Assert.equal([...ltm._builtInThemes].length, 3);
+  Assert.equal(ltm.usedThemes.length, 3);
+  Assert.equal(ltm.usedThemes[2].id, "builtInTheme1");
 
   // Clear all and then re-add
   ltm.clearBuiltInThemes();
   Assert.equal([...ltm._builtInThemes].length, 0);
   Assert.equal(ltm.usedThemes.length, 0);
 
   ltm.addBuiltInTheme(dummy("builtInTheme0"));
   ltm.addBuiltInTheme(dummy("builtInTheme1"));
--- a/toolkit/mozapps/extensions/test/xpcshell/test_addonStartup.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_addonStartup.js
@@ -1,28 +1,15 @@
 "use strict";
 
 add_task(async function test_XPIStates_invalid_paths() {
   let {path} = gAddonStartup;
 
   let startupDatasets = [
     {
-      "app-global": {
-        "addons": {
-          "{972ce4c6-7e08-4474-a285-3208198ce6fd}": {
-            "enabled": true,
-            "lastModifiedTime": 1,
-            "path": "{972ce4c6-7e08-4474-a285-3208198ce6fd}",
-            "type": "theme",
-            "version": "55.0a1",
-          }
-        },
-        "checkStartupModifications": true,
-        "path": "c:\\Program Files\\Mozilla Firefox\\extensions",
-      },
       "app-profile": {
         "addons": {
           "xpcshell-something-or-other@mozilla.org": {
             "bootstrapped": true,
             "dependencies": [],
             "enabled": true,
             "hasEmbeddedWebExtension": false,
             "lastModifiedTime": 1,
@@ -30,29 +17,16 @@ add_task(async function test_XPIStates_i
             "version": "0.0.0",
           },
         },
         "checkStartupModifications": true,
         "path": "/home/xpcshell/.mozilla/firefox/default/extensions",
       },
     },
     {
-      "app-global": {
-        "addons": {
-          "{972ce4c6-7e08-4474-a285-3208198ce6fd}": {
-            "enabled": true,
-            "lastModifiedTime": 1,
-            "path": "{972ce4c6-7e08-4474-a285-3208198ce6fd}",
-            "type": "theme",
-            "version": "55.0a1",
-          }
-        },
-        "checkStartupModifications": true,
-        "path": "c:\\Program Files\\Mozilla Firefox\\extensions",
-      },
       "app-profile": {
         "addons": {
           "xpcshell-something-or-other@mozilla.org": {
             "bootstrapped": true,
             "dependencies": [],
             "enabled": true,
             "hasEmbeddedWebExtension": false,
             "lastModifiedTime": 1,
--- a/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js
@@ -26,17 +26,17 @@ function run_test() {
 function end_test() {
   do_test_finished();
 }
 
 // Verify that with no add-ons installed the background update notifications get
 // called
 async function run_test_1() {
   let aAddons = await AddonManager.getAddonsByTypes(["extension", "theme", "locale"]);
-  Assert.equal(aAddons.length, 0);
+  Assert.equal(aAddons.length, 1);
 
   Services.obs.addObserver(function observer() {
     Services.obs.removeObserver(observer, "addons-background-update-complete");
 
     executeSoon(run_test_2);
   }, "addons-background-update-complete");
 
   // Trigger the background update timer handler
--- a/toolkit/mozapps/extensions/test/xpcshell/test_badschema.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_badschema.js
@@ -178,26 +178,26 @@ const ADDONS = {
       appDisabled: false,
       pendingOperations: 0,
     },
     afterCorruption: {},
     afterSecondRestart: {},
   },
 
   "theme1@tests.mozilla.org": {
-    "install.rdf": {
-      id: "theme1@tests.mozilla.org",
-      version: "1.0",
+    manifest: {
+      manifest_version: 2,
       name: "Theme 1",
-      internalName: "classic/1.0",
-      targetApplications: [{
-        id: "xpcshell@tests.mozilla.org",
-        minVersion: "2",
-        maxVersion: "2"
-      }]
+      version: "1.0",
+      theme: { images: { headerURL: "example.png" } },
+      applications: {
+        gecko: {
+          id: "theme1@tests.mozilla.org",
+        },
+      },
     },
     desiredValues: {
       isActive: false,
       userDisabled: true,
       appDisabled: false,
       pendingOperations: 0,
     },
     afterCorruption: {},
--- a/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js
@@ -597,39 +597,16 @@ const ADDONS = [
         maxVersion: "1"
       }],
       name: "Test Addon 26"
     },
     extraFiles: {"options.xul": ""},
     expected: null,
   },
 
-  // Theme manifests should ignore aboutURL and optionsURL.
-  {
-    "install.rdf": {
-      id: "bug371495@tests.mozilla.org",
-      version: "1.0",
-      type: "4",
-      internalName: "test/1.0",
-      optionsURL: "chrome://foo/content/bar.xul",
-      aboutURL: "chrome://foo/content/bar.xul",
-      name: "Test theme",
-      targetApplications: [{
-        id: "xpcshell@tests.mozilla.org",
-        minVersion: "1",
-        maxVersion: "1",
-      }],
-    },
-
-    expected: {
-      aboutURL: null,
-      optionsURL: null,
-    }
-  },
-
   // Tests compatibility based on target platforms.
 
   // No targetPlatforms so should be compatible
   {
     "install.rdf": {
       id: "tp-addon1@tests.mozilla.org",
       version: "1.0",
       bootstrap: true,
--- a/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js
@@ -42,35 +42,16 @@ const ADDONS = {
       }]
     },
     expected: {
       strictCompatibility: false,
     },
     compatible: [false, true,  false, true],
   },
 
-  // Theme - always uses strict compatibility, so is always incompatible
-  "addon3@tests.mozilla.org": {
-    "install.rdf": {
-      id: "addon3@tests.mozilla.org",
-      version: "1.0",
-      name: "Test 3",
-      internalName: "test-theme-3",
-      targetApplications: [{
-        id: "xpcshell@tests.mozilla.org",
-        minVersion: "0.8",
-        maxVersion: "0.9"
-      }]
-    },
-    expected: {
-      strictCompatibility: true,
-    },
-    compatible: [false, false, false, false],
-  },
-
   // Opt-in to strict compatibility - always incompatible
   "addon4@tests.mozilla.org": {
     "install.rdf": {
       id: "addon4@tests.mozilla.org",
       version: "1.0",
       name: "Test 4",
       bootstrap: true,
       strictCompatibility: true,
--- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_theme.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_theme.js
@@ -3,21 +3,22 @@
 /**
  * This file contains test for 'theme' type WebExtension addons. Tests focus mostly
  * on interoperability between the different theme formats (XUL and LWT) and
  * Addon Manager integration.
  *
  * Coverage may overlap with other tests in this folder.
  */
 
-const {LightweightThemeManager} = ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm", {});
+ChromeUtils.defineModuleGetter(this, "LightweightThemeManager",
+                               "resource://gre/modules/LightweightThemeManager.jsm");
 const THEME_IDS = [
   "theme3@tests.mozilla.org",
   "theme2@personas.mozilla.org",
-  "default@tests.mozilla.org"
+  "default-theme@mozilla.org",
 ];
 const DEFAULT_THEME = THEME_IDS[2];
 
 const profileDir = gProfD.clone();
 profileDir.append("extensions");
 
 // We remember the last/ currently active theme for tracking events.
 var gActiveTheme = null;
@@ -32,29 +33,16 @@ add_task(async function setup_to_default
     version: "1.0",
     theme: { images: { headerURL: "example.png" } },
     applications: {
       gecko: {
         id: THEME_IDS[0]
       }
     }
   }, profileDir);
-  // We need a default theme for some of these things to work but we have hidden
-  // the one in the application directory.
-  writeInstallRDFForExtension({
-    id: DEFAULT_THEME,
-    version: "1.0",
-    name: "Default",
-    internalName: "classic/1.0",
-    targetApplications: [{
-      id: "xpcshell@tests.mozilla.org",
-      minVersion: "1",
-      maxVersion: "2"
-    }]
-  }, profileDir);
 
   startupManager();
 
   // We can add an LWT only after the Addon Manager was started.
   LightweightThemeManager.currentTheme = {
     id: THEME_IDS[1].substr(0, THEME_IDS[1].indexOf("@")),
     version: "1",
     name: "Bling",
--- a/toolkit/mozapps/extensions/test/xpinstall/browser.ini
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser.ini
@@ -20,17 +20,16 @@ support-files =
   redirect.sjs
   restartless.xpi
   restartless-unsigned.xpi
   signed-no-cn.xpi
   signed-no-o.xpi
   signed.xpi
   slowinstall.sjs
   startsoftwareupdate.html
-  theme.xpi
   triggerredirect.html
   unsigned.xpi
 
 [browser_amosigned_trigger.js]
 [browser_amosigned_trigger_iframe.js]
 [browser_amosigned_url.js]
 [browser_auth.js]
 [browser_auth2.js]
deleted file mode 100644
index 74e650b4a8e01d96611d73cc27a597d14ee9dc23..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/toolkit/themes/linux/mozapps/jar.mn
+++ b/toolkit/themes/linux/mozapps/jar.mn
@@ -3,14 +3,8 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 toolkit.jar:
 #include ../../shared/mozapps.inc.mn
 * skin/classic/mozapps/extensions/extensions.css           (extensions/extensions.css)
   skin/classic/mozapps/extensions/heart.png                (extensions/heart.png)
   skin/classic/mozapps/profile/profileicon.png             (profile/profileicon.png)
   skin/classic/mozapps/update/updates.css                  (update/updates.css)
-
-#if MOZ_BUILD_APP == browser
-[browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#elif MOZ_SEPARATE_MANIFEST_FOR_THEME_OVERRIDES
-[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#endif
--- a/toolkit/themes/osx/global/jar.mn
+++ b/toolkit/themes/osx/global/jar.mn
@@ -77,14 +77,8 @@ toolkit.jar:
   skin/classic/global/icons/question-64.png                          (icons/question-64.png)
   skin/classic/global/icons/sslWarning.png                           (icons/sslWarning.png)
 * skin/classic/global/in-content/common.css                          (in-content/common.css)
 * skin/classic/global/in-content/info-pages.css                      (in-content/info-pages.css)
   skin/classic/global/tree/arrow-disclosure.svg                      (tree/arrow-disclosure.svg)
   skin/classic/global/tree/columnpicker.gif                          (tree/columnpicker.gif)
   skin/classic/global/tree/folder.png                                (tree/folder.png)
   skin/classic/global/tree/folder@2x.png                             (tree/folder@2x.png)
-
-#if MOZ_BUILD_APP == browser
-[browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#elif MOZ_SEPARATE_MANIFEST_FOR_THEME_OVERRIDES
-[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#endif
--- a/toolkit/themes/osx/mozapps/jar.mn
+++ b/toolkit/themes/osx/mozapps/jar.mn
@@ -18,14 +18,8 @@ toolkit.jar:
   skin/classic/mozapps/plugins/pluginHelp-16.png                  (plugins/pluginHelp-16.png)
   skin/classic/mozapps/profile/profileicon.png                    (profile/profileicon.png)
   skin/classic/mozapps/profile/profileSelection.css               (profile/profileSelection.css)
   skin/classic/mozapps/profile/profileicon-selected.png           (profile/profileicon-selected.png)
   skin/classic/mozapps/update/buttons.png                         (update/buttons.png)
 * skin/classic/mozapps/update/updates.css                         (update/updates.css)
   skin/classic/mozapps/xpinstall/xpinstallConfirm.css             (extensions/xpinstallConfirm.css)
   skin/classic/mozapps/handling/handling.css                      (handling/handling.css)
-
-#if MOZ_BUILD_APP == browser
-[browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#elif MOZ_SEPARATE_MANIFEST_FOR_THEME_OVERRIDES
-[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#endif
--- a/toolkit/themes/shared/non-mac.jar.inc.mn
+++ b/toolkit/themes/shared/non-mac.jar.inc.mn
@@ -46,14 +46,9 @@
   skin/classic/mozapps/extensions/cancel.png                 (../../windows/mozapps/extensions/cancel.png)
   skin/classic/mozapps/extensions/eula.css                   (../../windows/mozapps/extensions/eula.css)
   skin/classic/mozapps/handling/handling.css                 (../../windows/mozapps/handling/handling.css)
   skin/classic/mozapps/plugins/pluginHelp-16.png             (../../windows/mozapps/plugins/pluginHelp-16.png)
   skin/classic/mozapps/profile/profileSelection.css          (../../windows/mozapps/profile/profileSelection.css)
   skin/classic/mozapps/update/downloadButtons.png            (../../windows/mozapps/update/downloadButtons.png)
 * skin/classic/mozapps/xpinstall/xpinstallConfirm.css        (../../windows/mozapps/extensions/xpinstallConfirm.css)
 
-#if MOZ_BUILD_APP == browser
-[browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#elif MOZ_SEPARATE_MANIFEST_FOR_THEME_OVERRIDES
-[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#endif
 % override chrome://mozapps/skin/xpinstall/xpinstallItemGeneric.png       chrome://mozapps/skin/extensions/extensionGeneric.svg
--- a/toolkit/themes/windows/global/jar.mn
+++ b/toolkit/themes/windows/global/jar.mn
@@ -56,22 +56,16 @@ toolkit.jar:
   skin/classic/global/icons/Warning.png                    (icons/Warning.png)
   skin/classic/global/icons/warning-large.png              (icons/warning-large.png)
   skin/classic/global/icons/windowControls.png             (icons/windowControls.png)
 * skin/classic/global/in-content/common.css                (in-content/common.css)
 * skin/classic/global/in-content/info-pages.css            (in-content/info-pages.css)
   skin/classic/global/tree/twisty.svg                      (tree/twisty.svg)
   skin/classic/global/tree/twisty-preWin10.svg             (tree/twisty-preWin10.svg)
 
-#if MOZ_BUILD_APP == browser
-[browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#elif MOZ_SEPARATE_MANIFEST_FOR_THEME_OVERRIDES
-[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#endif
-
 % override chrome://global/skin/tree/twisty.svg#clsd              chrome://global/skin/tree/twisty-preWin10.svg#clsd           osversion<=6.3
 % override chrome://global/skin/tree/twisty.svg#clsd-rtl          chrome://global/skin/tree/twisty-preWin10.svg#clsd-rtl       osversion<=6.3
 % override chrome://global/skin/tree/twisty.svg#clsd-hover        chrome://global/skin/tree/twisty-preWin10.svg#clsd-hover     osversion<=6.3
 % override chrome://global/skin/tree/twisty.svg#clsd-hover-rtl    chrome://global/skin/tree/twisty-preWin10.svg#clsd-hover-rtl osversion<=6.3
 % override chrome://global/skin/tree/twisty.svg#open              chrome://global/skin/tree/twisty-preWin10.svg#open           osversion<=6.3
 % override chrome://global/skin/tree/twisty.svg#open-rtl          chrome://global/skin/tree/twisty-preWin10.svg#open-rtl       osversion<=6.3
 % override chrome://global/skin/tree/twisty.svg#open-hover        chrome://global/skin/tree/twisty-preWin10.svg#open-hover     osversion<=6.3
 % override chrome://global/skin/tree/twisty.svg#open-hover-rtl    chrome://global/skin/tree/twisty-preWin10.svg#open-hover-rtl osversion<=6.3
--- a/toolkit/themes/windows/mozapps/jar.mn
+++ b/toolkit/themes/windows/mozapps/jar.mn
@@ -3,14 +3,8 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 toolkit.jar:
 #include ../../shared/mozapps.inc.mn
 * skin/classic/mozapps/extensions/extensions.css             (extensions/extensions.css)
   skin/classic/mozapps/extensions/heart.png                  (extensions/heart.png)
   skin/classic/mozapps/profile/profileicon.png               (profile/profileicon.png)
   skin/classic/mozapps/update/updates.css                    (update/updates.css)
-
-#if MOZ_BUILD_APP == browser
-[browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#elif MOZ_SEPARATE_MANIFEST_FOR_THEME_OVERRIDES
-[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
-#endif