Bug 1682593: Remove the site specific browser feature. r=Gijs
authorDave Townsend <dtownsend@oxymoronical.com>
Fri, 15 Jan 2021 11:11:19 +0000 (2021-01-15)
changeset 563284 634e8801b8b6538dc9bdc43555185d68aa3f1886
parent 563283 c92dc02122c7e7b87d630ac15d51e6d772216096
child 563285 d5f4f4a54b905b2c5a56539579ace4f1f21cfb2c
push id134268
push userdtownsend@mozilla.com
push dateFri, 15 Jan 2021 14:03:11 +0000 (2021-01-15)
treeherderautoland@634e8801b8b6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1682593
milestone86.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 1682593: Remove the site specific browser feature. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D101860
browser/app/profile/firefox.js
browser/base/content/browser-pageActions.js
browser/base/content/browser.js
browser/base/content/browser.xhtml
browser/components/BrowserGlue.jsm
browser/components/moz.build
browser/components/ssb/ImageTools.jsm
browser/components/ssb/SiteSpecificBrowserChild.jsm
browser/components/ssb/SiteSpecificBrowserParent.jsm
browser/components/ssb/SiteSpecificBrowserService.jsm
browser/components/ssb/WindowsSupport.jsm
browser/components/ssb/components.conf
browser/components/ssb/content/jar.mn
browser/components/ssb/content/ssb.css
browser/components/ssb/content/ssb.html
browser/components/ssb/content/ssb.js
browser/components/ssb/moz.build
browser/components/ssb/tests/browser/browser.ini
browser/components/ssb/tests/browser/browser_ssb_direct.js
browser/components/ssb/tests/browser/browser_ssb_lasttab.js
browser/components/ssb/tests/browser/browser_ssb_list_menu.js
browser/components/ssb/tests/browser/browser_ssb_manifest_scope.js
browser/components/ssb/tests/browser/browser_ssb_menu.js
browser/components/ssb/tests/browser/browser_ssb_newtab.js
browser/components/ssb/tests/browser/browser_ssb_newwindow.js
browser/components/ssb/tests/browser/browser_ssb_open.js
browser/components/ssb/tests/browser/browser_ssb_windowlocation.js
browser/components/ssb/tests/browser/browser_ssb_windowopen.js
browser/components/ssb/tests/browser/empty_page.html
browser/components/ssb/tests/browser/head.js
browser/components/ssb/tests/browser/site1/allhost.html
browser/components/ssb/tests/browser/site1/allhost.json
browser/components/ssb/tests/browser/site1/bad.html
browser/components/ssb/tests/browser/site1/bad.json
browser/components/ssb/tests/browser/site1/empty.html
browser/components/ssb/tests/browser/site1/empty.json
browser/components/ssb/tests/browser/site1/final.html
browser/components/ssb/tests/browser/site1/simple.html
browser/components/ssb/tests/browser/site2/final.html
browser/components/ssb/tests/browser/test_page.html
browser/components/ssb/tests/xpcshell/head.js
browser/components/ssb/tests/xpcshell/test_empty.js
browser/components/ssb/tests/xpcshell/test_icons.js
browser/components/ssb/tests/xpcshell/test_install.js
browser/components/ssb/tests/xpcshell/test_manifest.js
browser/components/ssb/tests/xpcshell/test_too_new.js
browser/components/ssb/tests/xpcshell/test_uninstall.js
browser/components/ssb/tests/xpcshell/xpcshell.ini
browser/modules/PageActions.jsm
browser/themes/shared/install-ssb.svg
browser/themes/shared/jar.inc.mn
browser/themes/shared/menupanel.inc.css
browser/themes/shared/urlbar-searchbar.inc.css
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -2025,19 +2025,16 @@ pref("app.normandy.shieldLearnMoreUrl", 
 pref("app.normandy.last_seen_buildid", "");
 pref("app.normandy.onsync_skew_sec", 600);
 #ifdef MOZ_DATA_REPORTING
   pref("app.shield.optoutstudies.enabled", true);
 #else
   pref("app.shield.optoutstudies.enabled", false);
 #endif
 
-// Web apps support
-pref("browser.ssb.enabled", false);
-
 // Multi-lingual preferences
 #if defined(RELEASE_OR_BETA) && !defined(MOZ_DEV_EDITION)
   pref("intl.multilingual.enabled", true);
   pref("intl.multilingual.downloadEnabled", true);
 #else
   pref("intl.multilingual.enabled", false);
   // AMO only serves language packs for release and beta versions.
   pref("intl.multilingual.downloadEnabled", false);
--- a/browser/base/content/browser-pageActions.js
+++ b/browser/base/content/browser-pageActions.js
@@ -1,19 +1,14 @@
 /* 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/. */
 
 ChromeUtils.defineModuleGetter(
   this,
-  "SiteSpecificBrowser",
-  "resource:///modules/SiteSpecificBrowserService.jsm"
-);
-ChromeUtils.defineModuleGetter(
-  this,
   "SearchUIUtils",
   "resource:///modules/SearchUIUtils.jsm"
 );
 
 var BrowserPageActions = {
   _panelNode: null,
   /**
    * The main page action button in the urlbar (DOM node)
@@ -1128,43 +1123,16 @@ BrowserPageActions.pinTab = {
     if (gBrowser.selectedTab.pinned) {
       gBrowser.unpinTab(gBrowser.selectedTab);
     } else {
       gBrowser.pinTab(gBrowser.selectedTab);
     }
   },
 };
 
-// SiteSpecificBrowser
-BrowserPageActions.launchSSB = {
-  updateState() {
-    let action = PageActions.actionForID("launchSSB");
-    let browser = gBrowser.selectedBrowser;
-    action.setDisabled(!browser.currentURI.schemeIs("https"), window);
-  },
-
-  async onCommand(event, buttonNode) {
-    if (!gBrowser.currentURI.schemeIs("https")) {
-      return;
-    }
-
-    let ssb = await SiteSpecificBrowser.createFromBrowser(
-      gBrowser.selectedBrowser
-    );
-
-    // Launching through the UI implies installing.
-    await ssb.install();
-
-    // The site's manifest may point to a different start page so explicitly
-    // open the SSB to the current page.
-    ssb.launch(gBrowser.selectedBrowser.currentURI);
-    gBrowser.removeTab(gBrowser.selectedTab, { closeWindowWithLastTab: false });
-  },
-};
-
 // copy URL
 BrowserPageActions.copyURL = {
   onCommand(event, buttonNode) {
     PanelMultiView.hidePopup(BrowserPageActions.panelNode);
     Cc["@mozilla.org/widget/clipboardhelper;1"]
       .getService(Ci.nsIClipboardHelper)
       .copyString(
         gURLBar.makeURIReadable(gBrowser.selectedBrowser.currentURI).displaySpec
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -65,19 +65,16 @@ XPCOMUtils.defineLazyModuleGetters(this,
   SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
   Sanitizer: "resource:///modules/Sanitizer.jsm",
   SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
   SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
   ShortcutUtils: "resource://gre/modules/ShortcutUtils.jsm",
   SimpleServiceDiscovery: "resource://gre/modules/SimpleServiceDiscovery.jsm",
   SiteDataManager: "resource:///modules/SiteDataManager.jsm",
   SitePermissions: "resource:///modules/SitePermissions.jsm",
-  SiteSpecificBrowser: "resource:///modules/SiteSpecificBrowserService.jsm",
-  SiteSpecificBrowserService:
-    "resource:///modules/SiteSpecificBrowserService.jsm",
   SubDialogManager: "resource://gre/modules/SubDialog.jsm",
   TabModalPrompt: "chrome://global/content/tabprompts.jsm",
   TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
   TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
   Translation: "resource:///modules/translation/TranslationParent.jsm",
   UITour: "resource:///modules/UITour.jsm",
   UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
   UrlbarInput: "resource:///modules/UrlbarInput.jsm",
@@ -1925,18 +1922,16 @@ var gBrowserInit = {
     WebAuthnPromptHelper.init();
 
     // Initialize the full zoom setting.
     // We do this before the session restore service gets initialized so we can
     // apply full zoom settings to tabs restored by the session restore service.
     FullZoom.init();
     PanelUI.init();
 
-    SiteSpecificBrowserUI.init();
-
     UpdateUrlbarSearchSplitterState();
 
     BookmarkingUI.init();
     BrowserSearch.delayedStartupInit();
     gProtectionsHandler.init();
     HomePage.delayedStartup().catch(Cu.reportError);
 
     let safeMode = document.getElementById("helpSafeMode");
@@ -2562,140 +2557,16 @@ XPCOMUtils.defineLazyGetter(
   "_firstContentWindowPaintDeferred",
   () => PromiseUtils.defer()
 );
 
 gBrowserInit.idleTasksFinishedPromise = new Promise(resolve => {
   gBrowserInit.idleTaskPromiseResolve = resolve;
 });
 
-const SiteSpecificBrowserUI = {
-  menuInitialized: false,
-
-  init() {
-    if (!SiteSpecificBrowserService.isEnabled) {
-      return;
-    }
-
-    XPCOMUtils.defineLazyGetter(this, "panelBody", () => {
-      return PanelMultiView.getViewNode(
-        document,
-        "appMenu-SSBView .panel-subview-body"
-      );
-    });
-
-    let initializeMenu = async () => {
-      let list = await SiteSpecificBrowserService.list();
-
-      for (let ssb of list) {
-        this.addSSBToMenu(ssb);
-      }
-
-      if (!list.length) {
-        document.getElementById("appMenu-ssb-button").hidden = true;
-      }
-
-      this.menuInitialized = true;
-      Services.obs.addObserver(this, "site-specific-browser-install", true);
-      Services.obs.addObserver(this, "site-specific-browser-uninstall", true);
-    };
-
-    document.getElementById("appMenu-popup").addEventListener(
-      "popupshowing",
-      () => {
-        let blocker = initializeMenu();
-        PanelMultiView.getViewNode(
-          document,
-          "appMenu-SSBView"
-        ).addEventListener(
-          "ViewShowing",
-          event => {
-            event.detail.addBlocker(blocker);
-          },
-          { once: true }
-        );
-      },
-      { once: true }
-    );
-  },
-
-  observe(subject, topic, id) {
-    let ssb = SiteSpecificBrowser.get(id);
-    switch (topic) {
-      case "site-specific-browser-install":
-        this.addSSBToMenu(ssb);
-        break;
-      case "site-specific-browser-uninstall":
-        this.removeSSBFromMenu(ssb);
-        break;
-    }
-  },
-
-  removeSSBFromMenu(ssb) {
-    let container = document.getElementById("ssb-button-" + ssb.id);
-    if (!container) {
-      return;
-    }
-
-    if (!container.nextElementSibling && !container.previousElementSibling) {
-      document.getElementById("appMenu-ssb-button").hidden = true;
-    }
-
-    let button = container.querySelector(".ssb-launch");
-    let uri = button.getAttribute("image");
-    if (uri) {
-      URL.revokeObjectURL(uri);
-    }
-
-    container.remove();
-  },
-
-  addSSBToMenu(ssb) {
-    let container = document.createXULElement("toolbaritem");
-    container.id = `ssb-button-${ssb.id}`;
-    container.className = "toolbaritem-menu-buttons";
-
-    let menu = document.createXULElement("toolbarbutton");
-    menu.className = "ssb-launch subviewbutton subviewbutton-iconic";
-    menu.setAttribute("label", ssb.name);
-    menu.setAttribute("flex", "1");
-
-    ssb.getScaledIcon(16 * devicePixelRatio).then(
-      icon => {
-        if (icon) {
-          menu.setAttribute("image", URL.createObjectURL(icon));
-        }
-      },
-      error => {
-        console.error(error);
-      }
-    );
-
-    menu.addEventListener("command", () => {
-      ssb.launch();
-    });
-
-    let uninstall = document.createXULElement("toolbarbutton");
-    uninstall.className = "ssb-uninstall subviewbutton subviewbutton-iconic";
-    // Hardcoded for now. Localization tracked in bug 1602528.
-    uninstall.setAttribute("tooltiptext", "Uninstall");
-
-    uninstall.addEventListener("command", () => {
-      ssb.uninstall();
-    });
-
-    container.append(menu);
-    container.append(uninstall);
-    this.panelBody.append(container);
-    document.getElementById("appMenu-ssb-button").hidden = false;
-  },
-
-  QueryInterface: ChromeUtils.generateQI(["nsISupportsWeakReference"]),
-};
-
 function HandleAppCommandEvent(evt) {
   switch (evt.command) {
     case "Back":
       BrowserBack();
       break;
     case "Forward":
       BrowserForward();
       break;
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -863,22 +863,16 @@
                        oncommand="LoginHelper.openPasswordManager(window, { entryPoint: 'mainmenu' })"
                        />
         <toolbarbutton id="appMenu-addons-button"
                        class="subviewbutton subviewbutton-iconic"
                        label="&addons.label;"
                        key="key_openAddons"
                        command="Tools:Addons"
                        />
-        <toolbarbutton id="appMenu-ssb-button"
-                       class="subviewbutton subviewbutton-iconic subviewbutton-nav"
-                       label="Sites in App Mode"
-                       closemenu="none"
-                       oncommand="PanelUI.showSubView('appMenu-SSBView', this)"
-                       hidden="true" persist="hidden"/>
         <toolbarbutton id="appMenu-preferences-button"
                        class="subviewbutton subviewbutton-iconic"
 #ifdef XP_WIN
                        label="&preferencesCmd2.label;"
 #else
                        label="&preferencesCmdUnix.label;"
 #ifdef XP_MACOSX
                        key="key_preferencesCmdMac"
@@ -1179,21 +1173,16 @@
 
           <label id="PanelUI-panic-warning" data-l10n-id="panic-button-undo-warning"></label>
         </vbox>
         <button id="PanelUI-panic-view-button"
                 data-l10n-id="panic-button-forget-button"/>
       </vbox>
     </panelview>
 
-    <panelview id="appMenu-SSBView" class="PanelUI-subView">
-      <vbox class="panel-subview-body">
-      </vbox>
-    </panelview>
-
     <panelview id="appMenu-moreView" title="&moreMenu.label;" class="PanelUI-subView">
       <vbox class="panel-subview-body">
         <toolbarbutton id="appMenu-taskmanager-button"
                        class="subviewbutton subviewbutton-iconic"
                        label="&taskManagerCmd.label;"
                        oncommand="switchToTabHavingURI('about:performance', true)"/>
         <toolbarbutton id="appMenu-characterencoding-button"
                        class="subviewbutton subviewbutton-nav"
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -686,27 +686,16 @@ let JSWINDOWACTORS = {
   SwitchDocumentDirection: {
     child: {
       moduleURI: "resource:///actors/SwitchDocumentDirectionChild.jsm",
     },
 
     allFrames: true,
   },
 
-  SiteSpecificBrowser: {
-    parent: {
-      moduleURI: "resource:///actors/SiteSpecificBrowserParent.jsm",
-    },
-    child: {
-      moduleURI: "resource:///actors/SiteSpecificBrowserChild.jsm",
-    },
-
-    allFrames: true,
-  },
-
   Translation: {
     parent: {
       moduleURI: "resource:///modules/translation/TranslationParent.jsm",
     },
     child: {
       moduleURI: "resource:///modules/translation/TranslationChild.jsm",
       events: {
         pageshow: {},
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -48,17 +48,16 @@ DIRS += [
     "privatebrowsing",
     "prompts",
     "protections",
     "protocolhandler",
     "resistfingerprinting",
     "search",
     "sessionstore",
     "shell",
-    "ssb",
     "syncedtabs",
     "uitour",
     "urlbar",
     "translation",
 ]
 
 DIRS += ["build"]
 
deleted file mode 100644
--- a/browser/components/ssb/ImageTools.jsm
+++ /dev/null
@@ -1,137 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var EXPORTED_SYMBOLS = ["ImageTools"];
-
-const { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
-
-XPCOMUtils.defineLazyModuleGetters(this, {
-  FileUtils: "resource://gre/modules/FileUtils.jsm",
-  NetUtil: "resource://gre/modules/NetUtil.jsm",
-  Services: "resource://gre/modules/Services.jsm",
-});
-
-XPCOMUtils.defineLazyServiceGetter(
-  this,
-  "ImgTools",
-  "@mozilla.org/image/tools;1",
-  Ci.imgITools
-);
-
-XPCOMUtils.defineLazyGlobalGetters(this, ["Blob"]);
-
-const ImageTools = {
-  /**
-   * Given a data URI decodes the data into an object with "type" which is the
-   * found mimetype and "container" which is an imgIContainer.
-   *
-   * @param {nsIURI} dataURI the URI to load.
-   * @return {Promise<object>} the image info.
-   */
-  loadImage(dataURI) {
-    return new Promise((resolve, reject) => {
-      if (!dataURI.schemeIs("data")) {
-        reject(new Error("Should only be loading data URIs."));
-        return;
-      }
-
-      let channel = NetUtil.newChannel({
-        uri: dataURI,
-        loadUsingSystemPrincipal: true,
-      });
-
-      ImgTools.decodeImageFromChannelAsync(
-        dataURI,
-        channel,
-        (container, status) => {
-          if (Components.isSuccessCode(status)) {
-            resolve({
-              type: channel.contentType,
-              container,
-            });
-          } else {
-            reject(Components.Exception("Failed to load image.", status));
-          }
-        },
-        null
-      );
-    });
-  },
-
-  scaleImage(container, width, height) {
-    return new Promise((resolve, reject) => {
-      let stream = ImgTools.encodeScaledImage(
-        container,
-        "image/png",
-        width,
-        height,
-        ""
-      );
-
-      try {
-        stream.QueryInterface(Ci.nsIAsyncInputStream);
-      } catch (e) {
-        reject(
-          Components.Exception(
-            "imgIEncoder must implement nsIAsyncInputStream",
-            e
-          )
-        );
-      }
-
-      let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
-        Ci.nsIBinaryInputStream
-      );
-      binaryStream.setInputStream(stream);
-
-      let buffers = [];
-      let callback = () => {
-        try {
-          let available = binaryStream.available();
-          if (available) {
-            let buffer = new ArrayBuffer(available);
-            binaryStream.readArrayBuffer(available, buffer);
-            buffers.push(buffer);
-
-            stream.asyncWait(callback, 0, 0, Services.tm.mainThread);
-            return;
-          }
-
-          // No data available, assume the encoding is done.
-          resolve(new Blob(buffers));
-        } catch (e) {
-          reject(e);
-        }
-      };
-
-      try {
-        stream.asyncWait(callback, 0, 0, Services.tm.mainThread);
-      } catch (e) {
-        reject(e);
-      }
-    });
-  },
-
-  saveIcon(container, width, height, target) {
-    return new Promise((resolve, reject) => {
-      let output = FileUtils.openFileOutputStream(target);
-      let stream = ImgTools.encodeScaledImage(
-        container,
-        "image/vnd.microsoft.icon",
-        width,
-        height,
-        ""
-      );
-      NetUtil.asyncCopy(stream, output, status => {
-        if (Components.isSuccessCode(status)) {
-          resolve();
-        } else {
-          reject(Components.Exception("Failed to save icon.", status));
-        }
-      });
-    });
-  },
-};
deleted file mode 100644
--- a/browser/components/ssb/SiteSpecificBrowserChild.jsm
+++ /dev/null
@@ -1,177 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const EXPORTED_SYMBOLS = ["SiteSpecificBrowserChild"];
-
-const { SiteSpecificBrowserBase } = ChromeUtils.import(
-  "resource:///modules/SiteSpecificBrowserService.jsm"
-);
-const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const { E10SUtils } = ChromeUtils.import(
-  "resource://gre/modules/E10SUtils.jsm"
-);
-
-/**
- * Loads an icon URL into a data URI.
- *
- * @param {Window} window the DOM window providing the icon.
- * @param {string} uri the href for the icon, may be relative to the source page.
- * @return {Promise<string>} the data URI.
- */
-async function loadIcon(window, uri) {
-  let iconURL = new window.URL(uri, window.location);
-
-  let request = new window.Request(iconURL, { mode: "cors" });
-  request.overrideContentPolicyType(Ci.nsIContentPolicy.TYPE_IMAGE);
-
-  let response = await window.fetch(request);
-  let blob = await response.blob();
-
-  return new Promise((resolve, reject) => {
-    const reader = new FileReader();
-    reader.onloadend = () => resolve(reader.result);
-    reader.onerror = reject;
-    reader.readAsDataURL(blob);
-  });
-}
-
-class SiteSpecificBrowserChild extends JSWindowActorChild {
-  receiveMessage(message) {
-    switch (message.name) {
-      case "SetSSB":
-        // Note that this sets the webbrowserchrome for the top-level browser
-        // child in this page. This means that any inner-frames loading in
-        // different processes will not be handled correctly. Fixing this will
-        // happen in bug 1602849.
-        this.docShell.browserChild.webBrowserChrome = new WebBrowserChrome(
-          message.data
-        );
-        break;
-      case "LoadIcon":
-        return loadIcon(this.contentWindow, message.data);
-    }
-
-    return null;
-  }
-}
-
-function getActor(docShell) {
-  return docShell.domWindow.windowGlobalChild.getActor("SiteSpecificBrowser");
-}
-
-// JS actors can't generally be XPCOM objects so we must use a separate class.
-class WebBrowserChrome {
-  constructor(id) {
-    this.id = id;
-  }
-
-  get ssb() {
-    return SiteSpecificBrowserBase.get(this.id);
-  }
-
-  // nsIWebBrowserChrome3
-
-  /**
-   * This gets called when a user clicks on a link or submits a form. We can use
-   * it to see where the resulting page load will occur and if needed redirect
-   * it to a different target.
-   *
-   * @param {string}  originalTarget the target intended for the load.
-   * @param {nsIURI}  linkURI        the URI that will be loaded.
-   * @param {Node}    linkNode       the element causing the load.
-   * @param {boolean} isAppTab       whether the source docshell is marked as an
-   *                                 app tab.
-   * @return {string} the target to use for the load.
-   */
-  onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab) {
-    // Our actor is for the top-level frame in the page while this may be being
-    // called for a navigation in an inner frame. First we have to find the
-    // browsing context for the frame doing the load.
-
-    let docShell = linkNode.ownerGlobal.docShell;
-    let bc = docShell.browsingContext;
-
-    // Which browsing context is this link targetting?
-    let target = originalTarget ? bc.findWithName(originalTarget) : bc;
-
-    if (target) {
-      // If we found a target then it must be one of the frames within this
-      // frame tree since we don't support popup windows.
-      if (target.parent) {
-        // An inner frame, continue.
-        return originalTarget;
-      }
-
-      // A top-level load. If our SSB cannot load this URI then start the
-      // process of opening it into a new tab somewhere.
-      return this.ssb.canLoad(linkURI) ? originalTarget : "_blank";
-    }
-
-    // An attempt to open a new window/tab. If the new URI can be loaded by our
-    // SSB then load it at the top-level. Note that we override the requested
-    // target so that this page can't reach the new context.
-    return this.ssb.canLoad(linkURI) ? "_top" : "_blank";
-  }
-
-  /**
-   * A load is about to occur in a frame. This is an opportunity to stop it
-   * and redirect it somewhere.
-   *
-   * @param {nsIDocShell}     docShell            the current docshell.
-   * @param {nsIURI}          uri                 the URI that will be loaded.
-   * @param {nsIReferrerInfo} referrerInfo        the referrer info.
-   * @param {boolean}         hasPostData         whether there is POST data
-   *                                              for the load.
-   * @param {nsIPrincipal}    triggeringPrincipal the triggering principal.
-   * @param {nsIContentSecurityPolicy} csp the content security policy.
-   * @return {boolean} whether the load should proceed or not.
-   */
-  shouldLoadURI(
-    docShell,
-    uri,
-    referrerInfo,
-    hasPostData,
-    triggeringPrincipal,
-    csp
-  ) {
-    // As above, our actor is for the top-level frame in the page however we
-    // are passed the docshell potentially handling the load here so we can
-    // do the right thing.
-
-    // We only police loads at the top level.
-    if (docShell.browsingContext.parent) {
-      return true;
-    }
-
-    if (!this.ssb.canLoad(uri)) {
-      // Should only have got this far for a window.location manipulation.
-
-      getActor(docShell).sendAsyncMessage("RetargetOutOfScopeURIToBrowser", {
-        uri: uri.spec,
-        referrerInfo: E10SUtils.serializeReferrerInfo(referrerInfo),
-        triggeringPrincipal: E10SUtils.serializePrincipal(
-          triggeringPrincipal ||
-            Services.scriptSecurityManager.createNullPrincipal({})
-        ),
-        csp: csp ? E10SUtils.serializeCSP(csp) : null,
-      });
-
-      return false;
-    }
-
-    return true;
-  }
-
-  /**
-   * A simple check for whether this is the correct process to load this URI.
-   *
-   * @param {nsIURI}   uri  the URI that will be loaded.
-   * @return {boolean} whether the load should proceed or not.
-   */
-  shouldLoadURIInThisProcess(uri) {
-    return this.ssb.canLoad(uri);
-  }
-}
deleted file mode 100644
--- a/browser/components/ssb/SiteSpecificBrowserParent.jsm
+++ /dev/null
@@ -1,75 +0,0 @@
-/* vim: set ts=2 sw=2 sts=2 et tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-var EXPORTED_SYMBOLS = ["SiteSpecificBrowserParent"];
-
-const { BrowserWindowTracker } = ChromeUtils.import(
-  "resource:///modules/BrowserWindowTracker.jsm"
-);
-const { E10SUtils } = ChromeUtils.import(
-  "resource://gre/modules/E10SUtils.jsm"
-);
-const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const { AppConstants } = ChromeUtils.import(
-  "resource://gre/modules/AppConstants.jsm"
-);
-
-class SiteSpecificBrowserParent extends JSWindowActorParent {
-  receiveMessage(message) {
-    switch (message.name) {
-      case "RetargetOutOfScopeURIToBrowser":
-        // The content process found a URI that needs to be loaded in the main
-        // browser.
-        let triggeringPrincipal = E10SUtils.deserializePrincipal(
-          message.data.triggeringPrincipal
-        );
-        let referrerInfo = E10SUtils.deserializeReferrerInfo(
-          message.data.referrerInfo
-        );
-        let csp = E10SUtils.deserializeCSP(message.data.csp);
-
-        // Attempt to find an existing window to open it in.
-        let win = BrowserWindowTracker.getTopWindow();
-        if (win) {
-          win.gBrowser.selectedTab = win.gBrowser.addTab(message.data.uri, {
-            triggeringPrincipal,
-            csp,
-            referrerInfo,
-          });
-        } else {
-          let sa = Cc["@mozilla.org/array;1"].createInstance(
-            Ci.nsIMutableArray
-          );
-
-          let wuri = Cc["@mozilla.org/supports-string;1"].createInstance(
-            Ci.nsISupportsString
-          );
-          wuri.data = message.data.uri;
-
-          sa.appendElement(wuri);
-          sa.appendElement(null); // unused (bug 871161)
-          sa.appendElement(referrerInfo);
-          sa.appendElement(null); // postData
-          sa.appendElement(null); // allowThirdPartyFixup
-          sa.appendElement(null); // userContextId
-          sa.appendElement(null); // originPrincipal
-          sa.appendElement(null); // originStoragePrincipal
-          sa.appendElement(triggeringPrincipal);
-          sa.appendElement(null); // allowInheritPrincipal
-          sa.appendElement(csp);
-
-          Services.ww.openWindow(
-            null,
-            AppConstants.BROWSER_CHROME_URL,
-            null,
-            "chrome,dialog=no,all",
-            sa
-          );
-        }
-        break;
-    }
-  }
-}
deleted file mode 100644
--- a/browser/components/ssb/SiteSpecificBrowserService.jsm
+++ /dev/null
@@ -1,908 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * A Site Specific Browser intends to allow the user to navigate through the
- * chosen site in the SSB UI. Any attempt to load something outside the site
- * should be loaded in a normal browser. In order to achieve this we have to use
- * various APIs to listen for attempts to load new content and take appropriate
- * action. Often this requires returning synchronous responses to method calls
- * in content processes and will require data about the SSB in order to respond
- * correctly. Here we implement an architecture to support that:
- *
- * In the main process the SiteSpecificBrowser class implements all the
- * functionality involved with managing an SSB. All content processes can
- * synchronously retrieve a matching SiteSpecificBrowserBase that has enough
- * data about the SSB in order to be able to respond to load requests
- * synchronously. To support this we give every SSB a unique ID (UUID based)
- * and the appropriate data is shared via sharedData. Once created the ID can be
- * used to retrieve the SiteSpecificBrowser instance in the main process or
- * SiteSpecificBrowserBase instance in any content process.
- */
-
-var EXPORTED_SYMBOLS = [
-  "SiteSpecificBrowserService",
-  "SiteSpecificBrowserBase",
-  "SiteSpecificBrowser",
-  "SSBCommandLineHandler",
-];
-
-const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
-
-XPCOMUtils.defineLazyModuleGetters(this, {
-  ManifestObtainer: "resource://gre/modules/ManifestObtainer.jsm",
-  ManifestProcessor: "resource://gre/modules/ManifestProcessor.jsm",
-  KeyValueService: "resource://gre/modules/kvstore.jsm",
-  OS: "resource://gre/modules/osfile.jsm",
-  ImageTools: "resource:///modules/ssb/ImageTools.jsm",
-  AppConstants: "resource://gre/modules/AppConstants.jsm",
-});
-
-if (AppConstants.platform == "win") {
-  ChromeUtils.defineModuleGetter(
-    this,
-    "WindowsSupport",
-    "resource:///modules/ssb/WindowsSupport.jsm"
-  );
-}
-
-/**
- * A schema version for the SSB data stored in the kvstore.
- *
- * Version 1 has the `manifest` and `config` properties.
- */
-const DATA_VERSION = 1;
-
-/**
- * The prefix used for SSB ids in the store.
- */
-const SSB_STORE_PREFIX = "ssb:";
-
-/**
- * A prefix that will sort immediately after any SSB ids in the store.
- */
-const SSB_STORE_LAST = "ssb;";
-
-function uuid() {
-  return Cc["@mozilla.org/uuid-generator;1"]
-    .getService(Ci.nsIUUIDGenerator)
-    .generateUUID()
-    .toString();
-}
-
-const sharedDataKey = id => `SiteSpecificBrowserBase:${id}`;
-const storeKey = id => SSB_STORE_PREFIX + id;
-
-/**
- * Builds a lookup table for all the icons in order of size.
- */
-function buildIconList(icons) {
-  let iconList = [];
-
-  for (let icon of icons) {
-    for (let sizeSpec of icon.sizes) {
-      let size =
-        sizeSpec == "any" ? Number.MAX_SAFE_INTEGER : parseInt(sizeSpec);
-
-      iconList.push({
-        icon,
-        size,
-      });
-    }
-  }
-
-  iconList.sort((a, b) => {
-    // Given that we're using MAX_SAFE_INTEGER adding a value to that would
-    // overflow and give odd behaviour. And we're using numbers supplied by a
-    // website so just compare for safety.
-    if (a.size < b.size) {
-      return -1;
-    }
-
-    if (a.size > b.size) {
-      return 1;
-    }
-
-    return 0;
-  });
-  return iconList;
-}
-
-const IS_MAIN_PROCESS =
-  Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT;
-
-/**
- * Tests whether an app manifest's scope includes the given URI.
- *
- * @param {nsIURI} scope the manifest's scope.
- * @param {nsIURI} uri the URI to test.
- * @returns {boolean} true if the uri is included in the scope.
- */
-function scopeIncludes(scope, uri) {
-  // https://w3c.github.io/manifest/#dfn-within-scope
-  if (scope.prePath != uri.prePath) {
-    return false;
-  }
-
-  return uri.filePath.startsWith(scope.filePath);
-}
-
-/**
- * Generates a basic app manifest for a URI.
- *
- * @param {nsIURI} uri the start URI for the site.
- * @return {Manifest} an app manifest.
- */
-function manifestForURI(uri) {
-  try {
-    let manifestURI = Services.io.newURI("/manifest.json", null, uri);
-    return ManifestProcessor.process({
-      jsonText: "{}",
-      manifestURL: manifestURI.spec,
-      docURL: uri.spec,
-    });
-  } catch (e) {
-    console.error(`Failed to generate a SSB manifest for ${uri.spec}.`, e);
-    throw e;
-  }
-}
-
-/**
- * Creates an IconResource from the LinkHandler data.
- *
- * @param {object} iconData the data from the LinkHandler actor.
- * @return {Promise<IconResource>} an icon resource.
- */
-async function getIconResource(iconData) {
-  // This should be a data url so no network traffic.
-  let imageData = await ImageTools.loadImage(
-    Services.io.newURI(iconData.iconURL)
-  );
-  if (imageData.container.type == Ci.imgIContainer.TYPE_VECTOR) {
-    return {
-      src: iconData.iconURL,
-      purpose: ["any"],
-      type: imageData.type,
-      sizes: ["any"],
-    };
-  }
-
-  // TODO: For ico files we should find all the available sizes: Bug 1604285.
-
-  return {
-    src: iconData.iconURL,
-    purpose: ["any"],
-    type: imageData.type,
-    sizes: [`${imageData.container.width}x${imageData.container.height}`],
-  };
-}
-
-/**
- * Generates an app manifest for a site loaded in a browser element.
- *
- * @param {Element} browser the browser element the site is loaded in.
- * @return {Promise<Manifest>} an app manifest.
- */
-async function buildManifestForBrowser(browser) {
-  let manifest = null;
-  try {
-    manifest = await ManifestObtainer.browserObtainManifest(browser);
-  } catch (e) {
-    // We can function without a valid manifest.
-    console.error(e);
-  }
-
-  // Reject the manifest if its scope doesn't include the current document.
-  if (
-    !manifest ||
-    !scopeIncludes(Services.io.newURI(manifest.scope), browser.currentURI)
-  ) {
-    manifest = manifestForURI(browser.currentURI);
-  }
-
-  // Cache all the icons as data URIs since we can need access to them when
-  // the website is not loaded.
-  manifest.icons = (
-    await Promise.all(
-      manifest.icons.map(async icon => {
-        if (icon.src.startsWith("data:")) {
-          return icon;
-        }
-
-        let actor = browser.browsingContext.currentWindowGlobal.getActor(
-          "SiteSpecificBrowser"
-        );
-        try {
-          icon.src = await actor.sendQuery("LoadIcon", icon.src);
-        } catch (e) {
-          // Bad icon, drop it from the list.
-          return null;
-        }
-
-        return icon;
-      })
-    )
-  ).filter(icon => icon);
-
-  // If the site provided no icons then try to use the normal page icons.
-  if (!manifest.icons.length) {
-    let linkHandler = browser.browsingContext.currentWindowGlobal.getActor(
-      "LinkHandler"
-    );
-
-    for (let icon of [linkHandler.icon, linkHandler.richIcon]) {
-      if (!icon) {
-        continue;
-      }
-
-      try {
-        manifest.icons.push(await getIconResource(icon));
-      } catch (e) {
-        console.warn(`Failed to load icon resource ${icon.originalURL}`, e);
-      }
-    }
-  }
-
-  return manifest;
-}
-
-/**
- * Maintains an ID -> SSB mapping in the main process. Content processes should
- * use sharedData to get a SiteSpecificBrowserBase.
- *
- * We do not currently expire data from here so once created an SSB instance
- * lives for the lifetime of the application. The expectation is that the
- * numbers of different SSBs used will be low and the memory use will also
- * be low.
- */
-const SSBMap = new Map();
-
-/**
- * The base contains the data about an SSB instance needed in content processes.
- *
- * The only data needed currently is site's `scope` which is just a URI.
- */
-class SiteSpecificBrowserBase {
-  /**
-   * Creates a new SiteSpecificBrowserBase. Generally should only be called by
-   * code within this module.
-   *
-   * @param {nsIURI} scope the scope for the SSB.
-   */
-  constructor(scope) {
-    this._scope = scope;
-  }
-
-  /**
-   * Gets the SiteSpecifcBrowserBase for an ID. If this is the main process this
-   * will instead return the SiteSpecificBrowser instance itself but generally
-   * don't call this from the main process.
-   *
-   * The returned object is not "live" and will not be updated with any
-   * configuration changes from the main process so do not cache this, get it
-   * when needed and then discard.
-   *
-   * @param {string} id the SSB ID.
-   * @return {SiteSpecificBrowserBase|null} the instance if it exists.
-   */
-  static get(id) {
-    if (IS_MAIN_PROCESS) {
-      return SiteSpecificBrowser.get(id);
-    }
-
-    let key = sharedDataKey(id);
-    if (!Services.cpmm.sharedData.has(key)) {
-      return null;
-    }
-
-    let scope = Services.io.newURI(Services.cpmm.sharedData.get(key));
-    return new SiteSpecificBrowserBase(scope);
-  }
-
-  /**
-   * Checks whether the given URI is considered to be a part of this SSB or not.
-   * Any URIs that return false should be loaded in a normal browser.
-   *
-   * @param {nsIURI} uri the URI to check.
-   * @return {boolean} whether this SSB can load the URI.
-   */
-  canLoad(uri) {
-    // Always allow loading about:blank as it is the initial page for iframes.
-    if (uri.spec == "about:blank") {
-      return true;
-    }
-
-    return scopeIncludes(this._scope, uri);
-  }
-}
-
-/**
- * The SSB instance used in the main process.
- *
- * We maintain three pieces of data for an SSB:
- *
- * First is the string UUID for identification purposes.
- *
- * Second is an app manifest (https://w3c.github.io/manifest/). If the site does
- * not provide one a basic one will be automatically generated. The intent is to
- * never modify this such that it can be updated from the site when needed
- * without blowing away any configuration changes a user might want to make to
- * the SSB itself.
- *
- * Thirdly there is the SSB configuration. This includes internal data, user
- * overrides for the app manifest and custom SSB extensions to the app manifest.
- *
- * We pass data based on these down to the SiteSpecificBrowserBase in this and
- * other processes (via `_updateSharedData`).
- */
-class SiteSpecificBrowser extends SiteSpecificBrowserBase {
-  /**
-   * Creates a new SiteSpecificBrowser. Generally should only be called by
-   * code within this module.
-   *
-   * @param {string} id the SSB's unique ID.
-   * @param {Manifest} manifest the app manifest for the SSB.
-   * @param {object?} config the SSB configuration settings.
-   */
-  constructor(id, manifest, config = {}) {
-    if (!IS_MAIN_PROCESS) {
-      throw new Error(
-        "SiteSpecificBrowser instances are only available in the main process."
-      );
-    }
-
-    super(Services.io.newURI(manifest.scope));
-    this._id = id;
-    this._manifest = manifest;
-    this._config = Object.assign(
-      {
-        needsUpdate: true,
-        persisted: false,
-      },
-      config
-    );
-
-    // Cache the SSB for retrieval.
-    SSBMap.set(id, this);
-
-    this._updateSharedData();
-  }
-
-  /**
-   * Loads the SiteSpecificBrowser for the given ID.
-   *
-   * @param {string} id the SSB's unique ID.
-   * @param {object?} data the data to deserialize from. Do not use externally.
-   * @return {Promise<SiteSpecificBrowser?>} the instance if it exists.
-   */
-  static async load(id, data = null) {
-    if (!IS_MAIN_PROCESS) {
-      throw new Error(
-        "SiteSpecificBrowser instances are only available in the main process."
-      );
-    }
-
-    if (SSBMap.has(id)) {
-      return SSBMap.get(id);
-    }
-
-    if (!data) {
-      let kvstore = await SiteSpecificBrowserService.getKVStore();
-      data = await kvstore.get(storeKey(id), null);
-    }
-
-    if (!data) {
-      return null;
-    }
-
-    try {
-      let parsed = JSON.parse(data);
-      parsed.config.persisted = true;
-      return new SiteSpecificBrowser(id, parsed.manifest, parsed.config);
-    } catch (e) {
-      console.error(e);
-    }
-
-    return null;
-  }
-
-  /**
-   * Gets the SiteSpecifcBrowser for an ID. Can only be called from the main
-   * process.
-   *
-   * @param {string} id the SSB ID.
-   * @return {SiteSpecificBrowser|null} the instance if it exists.
-   */
-  static get(id) {
-    if (!IS_MAIN_PROCESS) {
-      throw new Error(
-        "SiteSpecificBrowser instances are only available in the main process."
-      );
-    }
-
-    return SSBMap.get(id);
-  }
-
-  /**
-   * Creates an SSB from a parsed app manifest.
-   *
-   * @param {Manifest} manifest the app manifest for the site.
-   * @return {Promise<SiteSpecificBrowser>} the generated SSB.
-   */
-  static async createFromManifest(manifest) {
-    if (!SiteSpecificBrowserService.isEnabled) {
-      throw new Error("Site specific browsing is disabled.");
-    }
-
-    if (!manifest.scope.startsWith("https:")) {
-      throw new Error(
-        "Site specific browsers can only be opened for secure sites."
-      );
-    }
-
-    return new SiteSpecificBrowser(uuid(), manifest, { needsUpdate: false });
-  }
-
-  /**
-   * Creates an SSB from a site loaded in a browser element.
-   *
-   * @param {Element} browser the browser element the site is loaded in.
-   * @return {Promise<SiteSpecificBrowser>} the generated SSB.
-   */
-  static async createFromBrowser(browser) {
-    if (!SiteSpecificBrowserService.isEnabled) {
-      throw new Error("Site specific browsing is disabled.");
-    }
-
-    if (!browser.currentURI.schemeIs("https")) {
-      throw new Error(
-        "Site specific browsers can only be opened for secure sites."
-      );
-    }
-
-    let manifest = await buildManifestForBrowser(browser);
-    let ssb = await SiteSpecificBrowser.createFromManifest(manifest);
-
-    if (!manifest.name) {
-      ssb.name = browser.contentTitle;
-    }
-    return ssb;
-  }
-
-  /**
-   * Creates an SSB from a sURI.
-   *
-   * @param {nsIURI} uri the uri to generate from.
-   * @return {SiteSpecificBrowser} the generated SSB.
-   */
-  static createFromURI(uri) {
-    if (!SiteSpecificBrowserService.isEnabled) {
-      throw new Error("Site specific browsing is disabled.");
-    }
-
-    if (!uri.schemeIs("https")) {
-      throw new Error(
-        "Site specific browsers can only be opened for secure sites."
-      );
-    }
-
-    return new SiteSpecificBrowser(uuid(), manifestForURI(uri));
-  }
-
-  /**
-   * Caches the data needed by content processes.
-   */
-  _updateSharedData() {
-    Services.ppmm.sharedData.set(sharedDataKey(this.id), this._scope.spec);
-    Services.ppmm.sharedData.flush();
-  }
-
-  /**
-   * Persists the data to the store if needed. When a change in configuration
-   * has occured call this.
-   */
-  async _maybeSave() {
-    // If this SSB is persisted then update it in the data store.
-    if (this._config.persisted) {
-      let data = {
-        manifest: this._manifest,
-        config: this._config,
-      };
-
-      let kvstore = await SiteSpecificBrowserService.getKVStore();
-      await kvstore.put(storeKey(this.id), JSON.stringify(data));
-    }
-  }
-
-  /**
-   * Installs this SiteSpecificBrowser such that it exists for future instances
-   * of the application and will appear in lists of installed SSBs.
-   */
-  async install() {
-    if (this._config.persisted) {
-      return;
-    }
-
-    this._config.persisted = true;
-    await this._maybeSave();
-
-    if (AppConstants.platform == "win") {
-      await WindowsSupport.install(this);
-    }
-
-    Services.obs.notifyObservers(
-      null,
-      "site-specific-browser-install",
-      this.id
-    );
-  }
-
-  /**
-   * Uninstalls this SiteSpecificBrowser. Undoes eveerything above. The SSB is
-   * still usable afterwards.
-   */
-  async uninstall() {
-    if (!this._config.persisted) {
-      return;
-    }
-
-    if (AppConstants.platform == "win") {
-      await WindowsSupport.uninstall(this);
-    }
-
-    this._config.persisted = false;
-    let kvstore = await SiteSpecificBrowserService.getKVStore();
-    await kvstore.delete(storeKey(this.id));
-
-    Services.obs.notifyObservers(
-      null,
-      "site-specific-browser-uninstall",
-      this.id
-    );
-  }
-
-  /**
-   * The SSB's ID.
-   */
-  get id() {
-    return this._id;
-  }
-
-  get name() {
-    if (this._config.name) {
-      return this._config.name;
-    }
-
-    if (this._manifest.name) {
-      return this._manifest.name;
-    }
-
-    return this.startURI.host;
-  }
-
-  set name(val) {
-    this._config.name = val;
-    this._maybeSave();
-  }
-
-  /**
-   * The default URI to load.
-   */
-  get startURI() {
-    return Services.io.newURI(this._manifest.start_url);
-  }
-
-  /**
-   * Whether this SSB needs to be checked for an updated manifest.
-   */
-  get needsUpdate() {
-    return this._config.needsUpdate;
-  }
-
-  /**
-   * Gets the best icon for the requested size. It may not be the exact size
-   * requested.
-   *
-   * Finds the smallest icon that is larger than the requested size. If no such
-   * icon exists returns the largest icon available. Returns null only if there
-   * are no icons at all.
-   *
-   * @param {Number} size the size of the desired icon in pixels.
-   * @return {IconResource} the icon resource for the icon.
-   */
-  getIcon(size) {
-    if (!this._iconSizes) {
-      this._iconSizes = buildIconList(this._manifest.icons);
-    }
-
-    if (!this._iconSizes.length) {
-      return null;
-    }
-
-    let i = 0;
-    while (i < this._iconSizes.length && this._iconSizes[i].size < size) {
-      i++;
-    }
-
-    return i < this._iconSizes.length
-      ? this._iconSizes[i].icon
-      : this._iconSizes[this._iconSizes.length - 1].icon;
-  }
-
-  /**
-   * Gets the best icon for the requested size. If there isn't a perfect match
-   * the closest match will be scaled.
-   *
-   * @param {Number} size the size of the desired icon in pixels.
-   * @return {string|null} a data URI for the icon.
-   */
-  async getScaledIcon(size) {
-    let icon = this.getIcon(size);
-    if (!icon) {
-      return null;
-    }
-
-    let { container } = await ImageTools.loadImage(
-      Services.io.newURI(icon.src)
-    );
-    return ImageTools.scaleImage(container, size, size);
-  }
-
-  /**
-   * Updates this SSB from a new app manifest.
-   *
-   * @param {Manifest} manifest the new app manifest.
-   */
-  async updateFromManifest(manifest) {
-    this._manifest = manifest;
-    this._iconSizes = null;
-    this._scope = Services.io.newURI(this._manifest.scope);
-    this._config.needsUpdate = false;
-
-    this._updateSharedData();
-    await this._maybeSave();
-  }
-
-  /**
-   * Updates this SSB from the site loaded in the browser element.
-   *
-   * @param {Element} browser the browser element.
-   */
-  async updateFromBrowser(browser) {
-    let manifest = await buildManifestForBrowser(browser);
-    await this.updateFromManifest(manifest);
-  }
-
-  /**
-   * Launches a SSB by opening the necessary UI.
-   *
-   * @param {nsIURI?} the initial URI to load. If not provided uses the default.
-   */
-  launch(uri = null) {
-    let sa = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
-
-    let idstr = Cc["@mozilla.org/supports-string;1"].createInstance(
-      Ci.nsISupportsString
-    );
-    idstr.data = this.id;
-    sa.appendElement(idstr);
-
-    if (uri) {
-      let uristr = Cc["@mozilla.org/supports-string;1"].createInstance(
-        Ci.nsISupportsString
-      );
-      uristr.data = uri.spec;
-      sa.appendElement(uristr);
-    }
-
-    let win = Services.ww.openWindow(
-      null,
-      "chrome://browser/content/ssb/ssb.html",
-      "_blank",
-      "chrome,dialog=no,all",
-      sa
-    );
-
-    if (Services.appinfo.OS == "WINNT") {
-      WindowsSupport.applyOSIntegration(this, win);
-    }
-  }
-}
-
-/**
- * Loads the KV store for SSBs. Should always resolve with a store even if that
- * means wiping whatever is currently on disk because it was unreadable.
- */
-async function loadKVStore() {
-  let dir = OS.Path.join(OS.Constants.Path.profileDir, "ssb");
-
-  /**
-   * Creates an empty store. Called when we know there is an empty directory.
-   */
-  async function createStore() {
-    await OS.File.makeDir(dir);
-    let kvstore = await KeyValueService.getOrCreate(dir, "ssb");
-    await kvstore.put(
-      "_meta",
-      JSON.stringify({
-        version: DATA_VERSION,
-      })
-    );
-
-    return kvstore;
-  }
-
-  // First see if anything exists.
-  try {
-    let info = await OS.File.stat(dir);
-
-    if (!info.isDir) {
-      await OS.File.remove(dir, { ignoreAbsent: true });
-      return createStore();
-    }
-  } catch (e) {
-    if (e.becauseNoSuchFile) {
-      return createStore();
-    }
-    throw e;
-  }
-
-  // Something exists, try to load it.
-  try {
-    let kvstore = await KeyValueService.getOrCreate(dir, "ssb");
-
-    let meta = await kvstore.get("_meta", null);
-    if (meta) {
-      let data = JSON.parse(meta);
-      if (data.version == DATA_VERSION) {
-        return kvstore;
-      }
-      console.error(`SSB store is an unexpected version ${data.version}`);
-    } else {
-      console.error("SSB store was missing meta data.");
-    }
-
-    // We don't know how to handle this database, re-initialize it.
-    await kvstore.clear();
-    await kvstore.put(
-      "_meta",
-      JSON.stringify({
-        version: DATA_VERSION,
-      })
-    );
-
-    return kvstore;
-  } catch (e) {
-    console.error(e);
-
-    // Something is very wrong. Wipe all our data and start again.
-    await OS.File.removeDir(dir);
-    return createStore();
-  }
-}
-
-const SiteSpecificBrowserService = {
-  kvstore: null,
-
-  /**
-   * Returns a promise that resolves to the KV store for SSBs.
-   */
-  getKVStore() {
-    if (!this.kvstore) {
-      this.kvstore = loadKVStore();
-    }
-
-    return this.kvstore;
-  },
-
-  /**
-   * Checks if OS integration is enabled. This will affect whether installs and
-   * uninstalls have effects on the OS itself amongst other things. Generally
-   * only disabled for testing.
-   */
-  get useOSIntegration() {
-    if (Services.appinfo.OS != "WINNT") {
-      return false;
-    }
-
-    return Services.prefs.getBoolPref("browser.ssb.osintegration", true);
-  },
-
-  /**
-   * Returns a promise that resolves to an array of all of the installed SSBs.
-   */
-  async list() {
-    let kvstore = await this.getKVStore();
-    let list = await kvstore.enumerate(SSB_STORE_PREFIX, SSB_STORE_LAST);
-    return Promise.all(
-      Array.from(list).map(({ key: id, value: data }) =>
-        SiteSpecificBrowser.load(id.substring(SSB_STORE_PREFIX.length), data)
-      )
-    );
-  },
-};
-
-XPCOMUtils.defineLazyPreferenceGetter(
-  SiteSpecificBrowserService,
-  "isEnabled",
-  "browser.ssb.enabled",
-  false
-);
-
-async function startSSB(id) {
-  // Loading the SSB is async. Until that completes and launches we will
-  // be without an open window and the platform will not continue startup
-  // in that case. Flag that a window is coming.
-  Services.startup.enterLastWindowClosingSurvivalArea();
-
-  // Whatever happens we must exitLastWindowClosingSurvivalArea when done.
-  try {
-    let ssb = await SiteSpecificBrowser.load(id);
-    if (ssb) {
-      ssb.launch();
-    } else {
-      dump(`No SSB installed as ID ${id}\n`);
-    }
-  } finally {
-    Services.startup.exitLastWindowClosingSurvivalArea();
-  }
-}
-
-class SSBCommandLineHandler {
-  /* nsICommandLineHandler */
-  handle(cmdLine) {
-    if (!SiteSpecificBrowserService.isEnabled) {
-      return;
-    }
-
-    let site = cmdLine.handleFlagWithParam("ssb", false);
-    if (site) {
-      cmdLine.preventDefault = true;
-
-      try {
-        let fixupInfo = Services.uriFixup.getFixupURIInfo(
-          site,
-          Services.uriFixup.FIXUP_FLAG_FIX_SCHEME_TYPOS
-        );
-
-        let uri = fixupInfo.preferredURI;
-        if (!uri) {
-          dump(`Unable to parse '${site}' as a URI.\n`);
-          return;
-        }
-
-        if (fixupInfo.fixupChangedProtocol && uri.schemeIs("http")) {
-          uri = uri
-            .mutate()
-            .setScheme("https")
-            .finalize();
-        }
-        let ssb = SiteSpecificBrowser.createFromURI(uri);
-        ssb.launch();
-      } catch (e) {
-        dump(`Unable to parse '${site}' as a URI: ${e}\n`);
-      }
-
-      return;
-    }
-
-    let id = cmdLine.handleFlagWithParam("start-ssb", false);
-    if (id) {
-      cmdLine.preventDefault = true;
-
-      startSSB(id);
-    }
-  }
-
-  get helpInfo() {
-    return "  --ssb <uri>        Open a site specific browser for <uri>.\n";
-  }
-}
-
-SSBCommandLineHandler.prototype.QueryInterface = ChromeUtils.generateQI([
-  "nsICommandLineHandler",
-]);
deleted file mode 100644
--- a/browser/components/ssb/WindowsSupport.jsm
+++ /dev/null
@@ -1,160 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var EXPORTED_SYMBOLS = ["WindowsSupport"];
-
-const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
-const { SiteSpecificBrowserService } = ChromeUtils.import(
-  "resource:///modules/SiteSpecificBrowserService.jsm"
-);
-
-XPCOMUtils.defineLazyModuleGetters(this, {
-  OS: "resource://gre/modules/osfile.jsm",
-  ImageTools: "resource:///modules/ssb/ImageTools.jsm",
-});
-
-const shellService = Cc["@mozilla.org/browser/shell-service;1"].getService(
-  Ci.nsIWindowsShellService
-);
-
-const uiUtils = Cc["@mozilla.org/windows-ui-utils;1"].getService(
-  Ci.nsIWindowsUIUtils
-);
-
-const taskbar = Cc["@mozilla.org/windows-taskbar;1"].getService(
-  Ci.nsIWinTaskbar
-);
-
-const File = Components.Constructor(
-  "@mozilla.org/file/local;1",
-  Ci.nsIFile,
-  "initWithPath"
-);
-
-function buildGroupId(id) {
-  try {
-    return `${taskbar.defaultGroupId}.ssb.${id}`;
-  } catch (e) {
-    return `Firefox.ssb.${id}`;
-  }
-}
-
-const WindowsSupport = {
-  /**
-   * Installs an SSB by creating a shortcut to launch it on the user's desktop.
-   *
-   * @param {SiteSpecificBrowser} ssb the SSB to install.
-   */
-  async install(ssb) {
-    if (!SiteSpecificBrowserService.useOSIntegration) {
-      return;
-    }
-
-    let dir = OS.Path.join(OS.Constants.Path.profileDir, "ssb", ssb.id);
-    await OS.File.makeDir(dir, {
-      from: OS.Constants.Path.profileDir,
-      ignoreExisting: true,
-    });
-
-    let iconFile = new File(OS.Path.join(dir, "icon.ico"));
-
-    // We should be embedding multiple icon sizes, but the current icon encoder
-    // does not support this. For now just embed a sensible size.
-    let icon = ssb.getIcon(128);
-    if (icon) {
-      let { container } = await ImageTools.loadImage(
-        Services.io.newURI(icon.src)
-      );
-      ImageTools.saveIcon(container, 128, 128, iconFile);
-    } else {
-      // TODO use a default icon file.
-      iconFile = null;
-    }
-
-    let desktop = Services.dirsvc.get("Desk", Ci.nsIFile);
-    let link = OS.Path.join(desktop.path, `${ssb.name}.lnk`);
-
-    shellService.createShortcut(
-      Services.dirsvc.get("XREExeF", Ci.nsIFile),
-      ["-profile", OS.Constants.Path.profileDir, "-start-ssb", ssb.id],
-      ssb.name,
-      iconFile,
-      buildGroupId(ssb.id),
-      new File(link)
-    );
-  },
-
-  /**
-   * Uninstalls an SSB by deleting its shortcut from the user's desktop.
-   *
-   * @param {SiteSpecificBrowser} ssb the SSB to uninstall.
-   */
-  async uninstall(ssb) {
-    if (!SiteSpecificBrowserService.useOSIntegration) {
-      return;
-    }
-
-    let desktop = Services.dirsvc.get("Desk", Ci.nsIFile);
-    let link = OS.Path.join(desktop.path, `${ssb.name}.lnk`);
-
-    try {
-      await OS.File.remove(link);
-    } catch (e) {
-      console.error(e);
-    }
-
-    let dir = OS.Path.join(OS.Constants.Path.profileDir, "ssb", ssb.id);
-    try {
-      await OS.File.removeDir(dir, {
-        ignoreAbsent: true,
-        ignorePermissions: true,
-      });
-    } catch (e) {
-      console.error(e);
-    }
-  },
-
-  /**
-   * Applies the necessary OS integration to an open SSB.
-   *
-   * Sets the window icon based on the available icons.
-   *
-   * @param {SiteSpecificBrowser} ssb the SSB.
-   * @param {DOMWindow} window the window showing the SSB.
-   */
-  async applyOSIntegration(ssb, window) {
-    const getIcon = async size => {
-      let icon = ssb.getIcon(size);
-      if (!icon) {
-        return null;
-      }
-
-      try {
-        let image = await ImageTools.loadImage(Services.io.newURI(icon.src));
-        return image.container;
-      } catch (e) {
-        console.error(e);
-        return null;
-      }
-    };
-
-    if (!SiteSpecificBrowserService.useOSIntegration) {
-      return;
-    }
-
-    let icons = await Promise.all([
-      getIcon(uiUtils.systemSmallIconSize),
-      getIcon(uiUtils.systemLargeIconSize),
-    ]);
-
-    if (icons[0] || icons[1]) {
-      uiUtils.setWindowIcon(window, icons[0], icons[1]);
-    }
-
-    taskbar.setGroupIdForWindow(window, buildGroupId(ssb.id));
-  },
-};
deleted file mode 100644
--- a/browser/components/ssb/components.conf
+++ /dev/null
@@ -1,19 +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/.
-
-Classes = [
-    {
-        'cid': '{6344f783-c893-4db8-91ec-7d43a46bd6f4}',
-        'contract_ids': [
-            '@mozilla.org/browser/ssb/clh;1',
-        ],
-        'jsm': 'resource:///modules/SiteSpecificBrowserService.jsm',
-        'constructor': 'SSBCommandLineHandler',
-        'categories': {
-            'command-line-handler': 'e-ssb',
-        },
-    },
-]
deleted file mode 100644
--- a/browser/components/ssb/content/jar.mn
+++ /dev/null
@@ -1,8 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-browser.jar:
-    content/browser/ssb/ssb.html
-    content/browser/ssb/ssb.js
-    content/browser/ssb/ssb.css
deleted file mode 100644
--- a/browser/components/ssb/content/ssb.css
+++ /dev/null
@@ -1,14 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-html,
-body,
-#browser-container,
-#browser {
-  width: 100%;
-  height: 100%;
-  margin: 0;
-  padding: 0;
-  overflow: hidden;
-}
deleted file mode 100644
--- a/browser/components/ssb/content/ssb.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE html>
-
-<html width="800" height="600">
-<head>
-<link rel="stylesheet" href="chrome://global/skin/global.css">
-<link rel="stylesheet" href="ssb.css">
-<title id="title"></title>
-</head>
-<body>
-  <div id="browser-container"></div>
-  <script type="text/javascript" src="ssb.js"></script>
-</body>
-</html>
deleted file mode 100644
--- a/browser/components/ssb/content/ssb.js
+++ /dev/null
@@ -1,269 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
-
-XPCOMUtils.defineLazyModuleGetters(this, {
-  BrowserUtils: "resource://gre/modules/BrowserUtils.jsm",
-  Services: "resource://gre/modules/Services.jsm",
-  SiteSpecificBrowser: "resource:///modules/SiteSpecificBrowserService.jsm",
-  BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
-  WindowsSupport: "resource:///modules/ssb/WindowsSupport.jsm",
-});
-
-XPCOMUtils.defineLazyScriptGetter(
-  this,
-  "PrintUtils",
-  "chrome://global/content/printUtils.js"
-);
-
-let gSSBBrowser = null;
-var gSSB = null;
-
-function init() {
-  gSSB = SiteSpecificBrowser.get(window.arguments[0]);
-
-  let uri = gSSB.startURI;
-  if (window.arguments.length > 1) {
-    uri = Services.io.newURI(window.arguments[1]);
-  }
-
-  window.browserDOMWindow = new BrowserDOMWindow();
-
-  gSSBBrowser = document.createXULElement("browser");
-  gSSBBrowser.setAttribute("id", "browser");
-  gSSBBrowser.setAttribute("type", "content");
-  gSSBBrowser.setAttribute("remote", "true");
-  gSSBBrowser.setAttribute("nodefaultsrc", "true");
-  document.getElementById("browser-container").appendChild(gSSBBrowser);
-
-  // Give our actor the SSB's ID.
-  let actor = gSSBBrowser.browsingContext.currentWindowGlobal.getActor(
-    "SiteSpecificBrowser"
-  );
-  actor.sendAsyncMessage("SetSSB", gSSB.id);
-
-  gSSBBrowser.addProgressListener(
-    new ProgressListener(),
-    Ci.nsIWebProgress.NOTIFY_STATE_ALL
-  );
-  gSSBBrowser.src = uri.spec;
-
-  document.getElementById("title").textContent = gSSB.name;
-}
-
-class ProgressListener {
-  constructor() {
-    this.isInitial = true;
-  }
-
-  /**
-   * Called when the load state changes
-   *
-   * @param {nsIWebProgress} webProgress
-   * @param {nsIRequest} request
-   * @param {Number} state
-   * @param {Number} status
-   */
-  async onStateChange(webProgress, request, state, status) {
-    if (!webProgress.isTopLevel) {
-      return;
-    }
-
-    let final =
-      Ci.nsIWebProgressListener.STATE_IS_WINDOW +
-      Ci.nsIWebProgressListener.STATE_STOP;
-    if ((state & final) != final) {
-      return;
-    }
-
-    // Load complete. Does the SSB need an update?
-    let { isInitial } = this;
-    this.isInitial = false;
-    if (isInitial && gSSB.needsUpdate) {
-      await gSSB.updateFromBrowser(gSSBBrowser);
-      if (Services.appinfo.OS == "WINNT") {
-        WindowsSupport.applyOSIntegration(gSSB, window);
-      }
-    }
-
-    // So the testing harness knows when the ssb is properly initialized.
-    let event = new CustomEvent("SSBLoad");
-    gSSBBrowser.dispatchEvent(event);
-  }
-}
-
-ProgressListener.prototype.QueryInterface = ChromeUtils.generateQI([
-  "nsIWebProgressListener",
-  "nsISupportsWeakReference",
-]);
-
-class BrowserDOMWindow {
-  /**
-   * Called when a page in the main process needs a new window to display a new
-   * page in.
-   *
-   * @param {nsIURI?} uri
-   * @param {nsIOpenWindowInfo} openWindowInfo
-   * @param {Number} where
-   * @param {Number} flags
-   * @param {nsIPrincipal} triggeringPrincipal
-   * @param {nsIContentSecurityPolicy?} csp
-   * @return {BrowsingContext} the BrowsingContext the URI should be loaded in.
-   */
-  createContentWindow(
-    uri,
-    openWindowInfo,
-    where,
-    flags,
-    triggeringPrincipal,
-    csp
-  ) {
-    console.error(
-      "createContentWindow should never be called from a remote browser"
-    );
-    throw Components.Exception("", Cr.NS_ERROR_FAILURE);
-  }
-
-  /**
-   * Called from a page in the main process to open a new URI.
-   *
-   * @param {nsIURI} uri
-   * @param {nsIOpenWindowInfo} openWindowInfo
-   * @param {Number} where
-   * @param {Number} flags
-   * @param {nsIPrincipal} triggeringPrincipal
-   * @param {nsIContentSecurityPolicy?} csp
-   * @return {BrowsingContext} the BrowsingContext the URI should be loaded in.
-   */
-  openURI(uri, openWindowInfo, where, flags, triggeringPrincipal, csp) {
-    console.error("openURI should never be called from a remote browser");
-    throw Components.Exception("", Cr.NS_ERROR_FAILURE);
-  }
-
-  /**
-   * Finds a new frame to load some content in.
-   *
-   * @param {nsIURI?} uri
-   * @param {nsIOpenURIInFrameParams} params
-   * @param {Number} where
-   * @param {Number} flags
-   * @param {string} name
-   * @param {boolean} shouldOpen should the load start or not.
-   * @return {Element} the frame element the URI should be loaded in.
-   */
-  getContentWindowOrOpenURIInFrame(
-    uri,
-    params,
-    where,
-    flags,
-    name,
-    shouldOpen
-  ) {
-    // It's been determined that this load needs to happen in a new frame.
-    // Either onBeforeLinkTraversal set this correctly or this is the result
-    // of a window.open call.
-    if (where == Ci.nsIBrowserDOMWindow.OPEN_PRINT_BROWSER) {
-      return PrintUtils.startPrintWindow(
-        "window_print",
-        params.openWindowInfo.parent,
-        { openWindowInfo: params.openWindowInfo }
-      );
-    }
-
-    // If this ssb can load the url then just load it internally.
-    if (gSSB.canLoad(uri)) {
-      return gSSBBrowser;
-    }
-
-    // Try and find a browser window to open in.
-    let win = BrowserWindowTracker.getTopWindow({
-      private: params.isPrivate,
-      allowPopups: false,
-    });
-
-    if (win) {
-      // Just hand off to the window's handler
-      win.focus();
-      return win.browserDOMWindow.openURIInFrame(
-        shouldOpen ? uri : null,
-        params,
-        where,
-        flags,
-        name
-      );
-    }
-
-    // We need to open a new browser window and a tab in it. That's an
-    // asychronous operation but luckily if we return null here the platform
-    // handles doing that for us.
-    return null;
-  }
-
-  /**
-   * Gets an nsFrameLoaderOwner to load some new content in.
-   *
-   * @param {nsIURI?} uri
-   * @param {nsIOpenURIInFrameParams} params
-   * @param {Number} where
-   * @param {Number} flags
-   * @param {string} name
-   * @return {Element} the frame element the URI should be loaded in.
-   */
-  createContentWindowInFrame(uri, params, where, flags, name) {
-    return this.getContentWindowOrOpenURIInFrame(
-      uri,
-      params,
-      where,
-      flags,
-      name,
-      false
-    );
-  }
-
-  /**
-   * Create a new nsFrameLoaderOwner and load some content into it.
-   *
-   * @param {nsIURI} uri
-   * @param {nsIOpenURIInFrameParams} params
-   * @param {Number} where
-   * @param {Number} flags
-   * @param {string} name
-   * @return {Element} the frame element the URI is loading in.
-   */
-  openURIInFrame(uri, params, where, flags, name) {
-    return this.getContentWindowOrOpenURIInFrame(
-      uri,
-      params,
-      where,
-      flags,
-      name,
-      true
-    );
-  }
-
-  canClose() {
-    /* globals docShell */
-    for (let i = 0; i < docShell.childCount; i++) {
-      let childShell = docShell.getChildAt(i).QueryInterface(Ci.nsIDocShell);
-      let { contentViewer } = childShell;
-      if (contentViewer && !contentViewer.permitUnload()) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  get tabCount() {
-    return 1;
-  }
-}
-
-BrowserDOMWindow.prototype.QueryInterface = ChromeUtils.generateQI([
-  "nsIBrowserDOMWindow",
-]);
-
-window.addEventListener("DOMContentLoaded", init, true);
deleted file mode 100644
--- a/browser/components/ssb/moz.build
+++ /dev/null
@@ -1,31 +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/.
-
-JAR_MANIFESTS += ["content/jar.mn"]
-BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.ini"]
-XPCSHELL_TESTS_MANIFESTS += ["tests/xpcshell/xpcshell.ini"]
-
-XPCOM_MANIFESTS += [
-    "components.conf",
-]
-
-EXTRA_JS_MODULES += [
-    "SiteSpecificBrowserService.jsm",
-]
-
-EXTRA_JS_MODULES.ssb += [
-    "ImageTools.jsm",
-]
-
-FINAL_TARGET_FILES.actors += [
-    "SiteSpecificBrowserChild.jsm",
-    "SiteSpecificBrowserParent.jsm",
-]
-
-if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
-    EXTRA_JS_MODULES.ssb += [
-        "WindowsSupport.jsm",
-    ]
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser.ini
+++ /dev/null
@@ -1,24 +0,0 @@
-[DEFAULT]
-support-files =
-  head.js
-  test_page.html
-  empty_page.html
-prefs =
-  dom.manfiest.enabled=true
-  browser.ssb.enabled=true
-  browser.ssb.osintegration=false
-
-[browser_ssb_direct.js]
-[browser_ssb_lasttab.js]
-[browser_ssb_list_menu.js]
-[browser_ssb_manifest_scope.js]
-support-files =
-  site1/*
-  site2/*
-[browser_ssb_menu.js]
-[browser_ssb_newtab.js]
-[browser_ssb_newwindow.js]
-[browser_ssb_open.js]
-[browser_ssb_windowlocation.js]
-[browser_ssb_windowopen.js]
-skip-if = true # It is unclear what we want to do here.
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_direct.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-async function testDirectLoad(target, checker) {
-  let ssb = await openSSB(gHttpsTestRoot + "test_page.html#" + target);
-
-  let promise = checker(ssb);
-  await BrowserTestUtils.synthesizeMouseAtCenter(
-    "#direct",
-    {},
-    getBrowser(ssb)
-  );
-
-  await promise;
-  await BrowserTestUtils.closeWindow(ssb);
-}
-
-// A link that should load inside the ssb
-add_task(async function local() {
-  await testDirectLoad(gHttpsTestRoot + "empty_page.html", async ssb => {
-    try {
-      await expectSSBLoad(ssb);
-      Assert.equal(
-        getBrowser(ssb).currentURI.spec,
-        gHttpsTestRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
-
-// A link to an insecure site should load outside the ssb
-add_task(async function insecure() {
-  await testDirectLoad(gHttpTestRoot + "empty_page.html", async ssb => {
-    try {
-      let tab = await expectTabLoad(ssb);
-      Assert.equal(
-        tab.linkedBrowser.currentURI.spec,
-        gHttpTestRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-      BrowserTestUtils.removeTab(tab);
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
-
-// A link to a different host should load outside the ssb
-add_task(async function external() {
-  await testDirectLoad(gHttpsOtherRoot + "empty_page.html", async ssb => {
-    try {
-      let tab = await expectTabLoad(ssb);
-      Assert.equal(
-        tab.linkedBrowser.currentURI.spec,
-        gHttpsOtherRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-      BrowserTestUtils.removeTab(tab);
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_lasttab.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Opening from the last browser tab should not close the window.
-add_task(async () => {
-  let win = await BrowserTestUtils.openNewBrowserWindow();
-
-  let windowClosed = false;
-  BrowserTestUtils.windowClosed(win).then(() => {
-    windowClosed = true;
-  });
-
-  Assert.equal(win.gBrowser.tabs.length, 1, "Should be only one tab.");
-  let tab = win.gBrowser.selectedTab;
-
-  BrowserTestUtils.loadURI(
-    win.gBrowser.selectedBrowser,
-    gHttpsTestRoot + "test_page.html"
-  );
-  await BrowserTestUtils.browserLoaded(
-    win.gBrowser.selectedBrowser,
-    true,
-    gHttpsTestRoot + "test_page.html"
-  );
-
-  let ssbwin = await openSSBFromBrowserWindow(win);
-  Assert.equal(win.gBrowser.tabs.length, 1, "Should still be only one tab.");
-  Assert.notEqual(tab, win.gBrowser.selectedTab, "Should be a new tab.");
-  Assert.equal(
-    getBrowser(ssbwin).currentURI.spec,
-    gHttpsTestRoot + "test_page.html"
-  );
-
-  await getSSB(ssbwin).uninstall();
-
-  Assert.ok(!windowClosed, "Should not have seen the window close.");
-  await BrowserTestUtils.closeWindow(ssbwin);
-  await BrowserTestUtils.closeWindow(win);
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_list_menu.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Check that the menu is updated correctly and can be used to launch an ssb.
-add_task(async () => {
-  let win = await BrowserTestUtils.openNewBrowserWindow();
-
-  let button = win.document.getElementById("appMenu-ssb-button");
-
-  Assert.equal(button, null, "Button should be not be available.");
-  Assert.equal(
-    win.document.querySelector("#appMenu-SSBView .panel-subview-body"),
-    null,
-    "Panel should not be available"
-  );
-
-  let ssb = await SiteSpecificBrowser.createFromURI(
-    Services.io.newURI(gHttpsTestRoot)
-  );
-
-  button = win.document.getElementById("appMenu-ssb-button");
-  Assert.equal(button, null, "Button should be not be available.");
-  Assert.equal(
-    win.document.querySelector("#appMenu-SSBView .panel-subview-body"),
-    null,
-    "Panel should not be available"
-  );
-
-  await ssb.install();
-
-  button = win.document.getElementById("appMenu-ssb-button");
-  // Button should still be unavailable, we don't populate the list until it is
-  // first opened.
-  Assert.equal(button, null, "Button should be not be available.");
-  Assert.equal(
-    win.document.querySelector("#appMenu-SSBView .panel-subview-body"),
-    null,
-    "Panel should not be available"
-  );
-
-  let appMenuOpened = BrowserTestUtils.waitForEvent(
-    win.document.getElementById("appMenu-popup"),
-    "popupshown"
-  );
-
-  EventUtils.synthesizeMouseAtCenter(
-    win.document.getElementById("PanelUI-menu-button"),
-    {},
-    win
-  );
-  await appMenuOpened;
-
-  button = win.document.getElementById("appMenu-ssb-button");
-  await BrowserTestUtils.waitForAttributeRemoval("hidden", button);
-
-  Assert.ok(!button.hidden, "Button should be visible.");
-
-  EventUtils.synthesizeMouseAtCenter(
-    win.document.getElementById("appMenu-ssb-button"),
-    {},
-    win
-  );
-
-  let panelShown = BrowserTestUtils.waitForEvent(
-    win.document.getElementById("appMenu-SSBView"),
-    "ViewShown"
-  );
-  let panel = win.document.querySelector(
-    "#appMenu-SSBView .panel-subview-body"
-  );
-  await panelShown;
-
-  Assert.notEqual(
-    panel.firstElementChild,
-    null,
-    "Should be something in the list."
-  );
-  Assert.equal(
-    panel.firstElementChild.id,
-    "ssb-button-" + ssb.id,
-    "Should have the right ID."
-  );
-
-  let ssbOpened = waitForSSB();
-  EventUtils.synthesizeMouseAtCenter(panel.firstElementChild, {}, win);
-  let ssbWin = await ssbOpened;
-
-  Assert.equal(getBrowser(ssbWin).currentURI.spec, gHttpsTestRoot);
-  await BrowserTestUtils.closeWindow(ssbWin);
-
-  await ssb.uninstall();
-
-  // Menu will be dynamically updating at this point.
-  Assert.ok(button.hidden, "Should be no installs.");
-  Assert.equal(panel.firstElementChild, null, "Should be nothing in the list.");
-
-  await BrowserTestUtils.closeWindow(win);
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_manifest_scope.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Enable web manifest processing.
-Services.prefs.setBoolPref("dom.manifest.enabled", true);
-
-// Check that a site's manifest affects the scope of a ssb.
-
-function build_task(page, linkId, external, preload) {
-  let expectedTarget = linkId + "/final.html";
-
-  add_task(async () => {
-    let ssbwin;
-
-    info(`Loading ${page} (${preload})`);
-    if (preload) {
-      // Loading via a browser will initialize the SSB with the correct manifest.
-      await BrowserTestUtils.openNewForegroundTab({
-        gBrowser,
-        url: gHttpsTestRoot + page,
-      });
-
-      ssbwin = await openSSBFromBrowserWindow();
-    } else {
-      // The manifest will be loaded once the initial page loads.
-      ssbwin = await openSSB(gHttpsTestRoot + page);
-    }
-
-    let promise;
-    if (external) {
-      promise = expectTabLoad(ssbwin).then(tab => {
-        Assert.equal(
-          tab.linkedBrowser.currentURI.spec,
-          gHttpsTestRoot + expectedTarget,
-          "Should have loaded the right uri."
-        );
-        BrowserTestUtils.removeTab(tab);
-      });
-    } else {
-      promise = expectSSBLoad(ssbwin).then(() => {
-        Assert.equal(
-          getBrowser(ssbwin).currentURI.spec,
-          gHttpsTestRoot + expectedTarget,
-          "Should have loaded the right uri."
-        );
-      });
-    }
-
-    info(`Clicking #${linkId}`);
-    await BrowserTestUtils.synthesizeMouseAtCenter(
-      `#${linkId}`,
-      {},
-      getBrowser(ssbwin)
-    );
-
-    await promise;
-    await getSSB(ssbwin).uninstall();
-    await BrowserTestUtils.closeWindow(ssbwin);
-  });
-}
-
-function make_all_tasks(preload) {
-  /**
-   * Arguments are:
-   *
-   * * Page to load.
-   * * Link ID to click in the page.
-   * * Is that link expected to point to an external site (i.e. should be retargeted).
-   * * true to create the SSB from a loaded browser, false to create it from a URL.
-   *     The latter implies that the manifest won't initially be available.
-   */
-  build_task("site1/simple.html", "site1", false, preload);
-  build_task("site1/simple.html", "site2", true, preload);
-  build_task("site1/empty.html", "site1", false, preload);
-  build_task("site1/empty.html", "site2", true, preload);
-  build_task("site1/allhost.html", "site1", false, preload);
-  build_task("site1/allhost.html", "site2", false, preload);
-  build_task("site1/bad.html", "site1", false, preload);
-  build_task("site1/bad.html", "site2", true, preload);
-}
-
-make_all_tasks(true);
-make_all_tasks(false);
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_menu.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Check that it is correctly enabled/disabled based on the displaying page.
-add_task(async () => {
-  let tab = await BrowserTestUtils.openNewForegroundTab({
-    gBrowser,
-    url: gHttpTestRoot + "test_page.html",
-  });
-
-  // Must open the panel before the item gets added.
-  let pageActionButton = document.getElementById("pageActionButton");
-  let panel = document.getElementById("pageActionPanel");
-  let popupShown = BrowserTestUtils.waitForEvent(panel, "popupshown");
-
-  EventUtils.synthesizeMouseAtCenter(pageActionButton, {}, window);
-  await popupShown;
-
-  let popupHidden = BrowserTestUtils.waitForEvent(panel, "popuphidden");
-  panel.hidePopup();
-  await popupHidden;
-
-  Assert.ok(
-    document.getElementById("pageAction-panel-launchSSB").disabled,
-    "Menu should be disabled for a http: page."
-  );
-
-  let uri = gHttpsTestRoot + "test_page.html";
-  BrowserTestUtils.loadURI(tab.linkedBrowser, uri);
-  await BrowserTestUtils.browserLoaded(tab.linkedBrowser, true, uri);
-
-  Assert.ok(
-    !document.getElementById("pageAction-panel-launchSSB").disabled,
-    "Menu should not be disabled for a https: page."
-  );
-
-  BrowserTestUtils.removeTab(tab);
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_newtab.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-async function testNewTabLoad(target, checker) {
-  let ssb = await openSSB(gHttpsTestRoot + "test_page.html#" + target);
-
-  let promise = checker(ssb);
-  await BrowserTestUtils.synthesizeMouseAtCenter(
-    "#new-tab",
-    {},
-    getBrowser(ssb)
-  );
-
-  await promise;
-  await BrowserTestUtils.closeWindow(ssb);
-}
-
-// A link that should load inside the ssb
-add_task(async function local() {
-  await testNewTabLoad(gHttpsTestRoot + "empty_page.html", async ssb => {
-    try {
-      await expectSSBLoad(ssb);
-      Assert.equal(
-        getBrowser(ssb).currentURI.spec,
-        gHttpsTestRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
-
-// A link to an insecure site should load outside the ssb
-add_task(async function insecure() {
-  await testNewTabLoad(gHttpTestRoot + "empty_page.html", async ssb => {
-    try {
-      let tab = await expectTabLoad(ssb);
-      Assert.equal(
-        tab.linkedBrowser.currentURI.spec,
-        gHttpTestRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-      BrowserTestUtils.removeTab(tab);
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
-
-// A link to a different host should load outside the ssb
-add_task(async function external() {
-  await testNewTabLoad(gHttpsOtherRoot + "empty_page.html", async ssb => {
-    try {
-      let tab = await expectTabLoad(ssb);
-      Assert.equal(
-        tab.linkedBrowser.currentURI.spec,
-        gHttpsOtherRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-      BrowserTestUtils.removeTab(tab);
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_newwindow.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-async function testNewWindowLoad(target, checker) {
-  let ssb = await openSSB(gHttpsTestRoot + "test_page.html#" + target);
-
-  let promise = checker(ssb);
-  await BrowserTestUtils.synthesizeMouseAtCenter(
-    "#new-window",
-    {},
-    getBrowser(ssb)
-  );
-
-  await promise;
-  await BrowserTestUtils.closeWindow(ssb);
-}
-
-// A link that should load inside the ssb
-add_task(async function local() {
-  await testNewWindowLoad(gHttpsTestRoot + "empty_page.html", async ssb => {
-    try {
-      await expectSSBLoad(ssb);
-      Assert.equal(
-        getBrowser(ssb).currentURI.spec,
-        gHttpsTestRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
-
-// A link to an insecure site should load outside the ssb
-add_task(async function insecure() {
-  await testNewWindowLoad(gHttpTestRoot + "empty_page.html", async ssb => {
-    try {
-      let tab = await expectTabLoad(ssb);
-      Assert.equal(
-        tab.linkedBrowser.currentURI.spec,
-        gHttpTestRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-      BrowserTestUtils.removeTab(tab);
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
-
-// A link to a different host should load outside the ssb
-add_task(async function external() {
-  await testNewWindowLoad(gHttpsOtherRoot + "empty_page.html", async ssb => {
-    try {
-      let tab = await expectTabLoad(ssb);
-      Assert.equal(
-        tab.linkedBrowser.currentURI.spec,
-        gHttpsOtherRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-      BrowserTestUtils.removeTab(tab);
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_open.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Verify that clicking the menu button opens an ssb.
-add_task(async () => {
-  let tab = await BrowserTestUtils.openNewForegroundTab({
-    gBrowser,
-    url: gHttpsTestRoot + "test_page.html",
-  });
-
-  let ssbwin = await openSSBFromBrowserWindow();
-  Assert.equal(
-    getBrowser(ssbwin).currentURI.spec,
-    gHttpsTestRoot + "test_page.html"
-  );
-
-  Assert.equal(tab.parentNode, null, "The tab should have been closed");
-  let ssb = getSSB(ssbwin);
-
-  // This title comes from the test_page.html title tag as there is no manifest.
-  Assert.equal(ssb.name, "Test site", "The name should be correct.");
-
-  await ssb.uninstall();
-  await BrowserTestUtils.closeWindow(ssbwin);
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_windowlocation.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-async function testWindowLocationLoad(target, checker) {
-  let ssb = await openSSB(gHttpsTestRoot + "test_page.html#" + target);
-
-  let promise = checker(ssb);
-  await BrowserTestUtils.synthesizeMouseAtCenter(
-    "#window-location",
-    {},
-    getBrowser(ssb)
-  );
-
-  await promise;
-  await BrowserTestUtils.closeWindow(ssb);
-}
-
-// A link that should load inside the ssb
-add_task(async function local() {
-  await testWindowLocationLoad(
-    gHttpsTestRoot + "empty_page.html",
-    async ssb => {
-      try {
-        await expectSSBLoad(ssb);
-        Assert.equal(
-          getBrowser(ssb).currentURI.spec,
-          gHttpsTestRoot + "empty_page.html",
-          "Should have loaded the right uri."
-        );
-      } catch (e) {
-        // Any error will already have logged a failure.
-      }
-    }
-  );
-});
-
-// A link to an insecure site should load outside the ssb
-add_task(async function insecure() {
-  await testWindowLocationLoad(gHttpTestRoot + "empty_page.html", async ssb => {
-    try {
-      let tab = await expectTabLoad(ssb);
-      Assert.equal(
-        tab.linkedBrowser.currentURI.spec,
-        gHttpTestRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-      BrowserTestUtils.removeTab(tab);
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
-
-// A link to a different host should load outside the ssb
-add_task(async function external() {
-  await testWindowLocationLoad(
-    gHttpsOtherRoot + "empty_page.html",
-    async ssb => {
-      try {
-        let tab = await expectTabLoad(ssb);
-        Assert.equal(
-          tab.linkedBrowser.currentURI.spec,
-          gHttpsOtherRoot + "empty_page.html",
-          "Should have loaded the right uri."
-        );
-        BrowserTestUtils.removeTab(tab);
-      } catch (e) {
-        // Any error will already have logged a failure.
-      }
-    }
-  );
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/browser_ssb_windowopen.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-async function testWindowOpenLoad(target, checker) {
-  let ssb = await openSSB(gHttpsTestRoot + "test_page.html#" + target);
-
-  let promise = checker(ssb);
-  await BrowserTestUtils.synthesizeMouseAtCenter(
-    "#window-open",
-    {},
-    getBrowser(ssb)
-  );
-
-  await promise;
-  await BrowserTestUtils.closeWindow(ssb);
-}
-
-// A link that should load inside the ssb
-add_task(async function local() {
-  await testWindowOpenLoad(gHttpsTestRoot + "empty_page.html", async ssb => {
-    try {
-      await expectSSBLoad(ssb);
-      Assert.equal(
-        getBrowser(ssb).currentURI.spec,
-        gHttpsTestRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
-
-// A link to an insecure site should load outside the ssb
-add_task(async function insecure() {
-  await testWindowOpenLoad(gHttpTestRoot + "empty_page.html", async ssb => {
-    try {
-      let tab = await expectTabLoad(ssb);
-      Assert.equal(
-        tab.linkedBrowser.currentURI.spec,
-        gHttpTestRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-      BrowserTestUtils.removeTab(tab);
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
-
-// A link to a different host should load outside the ssb
-add_task(async function external() {
-  await testWindowOpenLoad(gHttpsOtherRoot + "empty_page.html", async ssb => {
-    try {
-      let tab = await expectTabLoad(ssb);
-      Assert.equal(
-        tab.linkedBrowser.currentURI.spec,
-        gHttpsOtherRoot + "empty_page.html",
-        "Should have loaded the right uri."
-      );
-      BrowserTestUtils.removeTab(tab);
-    } catch (e) {
-      // Any error will already have logged a failure.
-    }
-  });
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/empty_page.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<meta charset="utf-8">
-</head>
-<body>
-</body>
-</html>
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/head.js
+++ /dev/null
@@ -1,225 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const { SiteSpecificBrowser } = ChromeUtils.import(
-  "resource:///modules/SiteSpecificBrowserService.jsm"
-);
-
-// An insecure site to use. SSBs cannot be insecure.
-const gHttpTestRoot = getRootDirectory(gTestPath).replace(
-  "chrome://mochitests/content/",
-  "http://example.com/"
-);
-
-// A secure site to use.
-const gHttpsTestRoot = getRootDirectory(gTestPath).replace(
-  "chrome://mochitests/content/",
-  "https://example.com/"
-);
-
-// A different secure site to use.
-const gHttpsOtherRoot = getRootDirectory(gTestPath).replace(
-  "chrome://mochitests/content/",
-  "https://example.org/"
-);
-
-// The chrome url for the SSB UI.
-const SSB_WINDOW = "chrome://browser/content/ssb/ssb.html";
-
-// Waits for an SSB window to open.
-async function waitForSSB() {
-  let ssbwin = await BrowserTestUtils.domWindowOpened(null, async domwin => {
-    await BrowserTestUtils.waitForEvent(domwin, "load");
-    return domwin.location.toString() == SSB_WINDOW;
-  });
-
-  await BrowserTestUtils.waitForEvent(getBrowser(ssbwin), "SSBLoad");
-  return ssbwin;
-}
-
-// Directly opens an SSB for the given URI. Resolves to the SSB DOM window after
-// the SSB content has loaded.
-async function openSSB(uri) {
-  if (!(uri instanceof Ci.nsIURI)) {
-    uri = Services.io.newURI(uri);
-  }
-
-  let openPromise = waitForSSB();
-  let ssb = SiteSpecificBrowser.createFromURI(uri);
-  ssb.launch();
-  return openPromise;
-}
-
-// Simulates opening a SSB from the main browser window. Resolves to the SSB
-// DOM window after the SSB content has loaded.
-async function openSSBFromBrowserWindow(win = window) {
-  let doc = win.document;
-  let pageActionButton = doc.getElementById("pageActionButton");
-  EventUtils.synthesizeMouseAtCenter(pageActionButton, {}, win);
-  let panel = doc.getElementById("pageActionPanel");
-  let popupShown = BrowserTestUtils.waitForEvent(panel, "popupshown");
-
-  await popupShown;
-
-  let openItem = doc.getElementById("pageAction-panel-launchSSB");
-  Assert.ok(!openItem.disabled, "Open menu item should not be disabled");
-  Assert.ok(!openItem.hidden, "Open menu item should not be hidden");
-
-  let openPromise = waitForSSB();
-  EventUtils.synthesizeMouseAtCenter(openItem, {}, win);
-  return openPromise;
-}
-
-// Given the SSB UI DOM window gets the browser element showing the content.
-function getBrowser(ssbwin) {
-  return ssbwin.document.getElementById("browser");
-}
-
-// Given the SSB UI DOM window gets the ssb instance showing the content.
-function getSSB(ssbwin) {
-  return ssbwin.gSSB;
-}
-
-/**
- * Waits for a load in response to an attempt to navigate from the SSB. It
- * listens for new tab opens in the main window, new window opens and loads in
- * the SSB itself. It returns a promise.
- *
- * The `where` argument is a string saying where the load is expected to
- * happen, "ssb", "tab" or "window". The promise rejects if the load happens
- * somewhere else and the offending new item (tab or window) get closed. When
- * the load is seen in the correct location different things are returned
- * depending on `where`. For "tab" the new tab is returned (it will have
- * finished loading), for "window" the new window is returned (it will have
- * finished loading). The "ssb" case doesn't return anything.
- *
- * Generally use the methods below this as they look more obvious.
- */
-function expectLoadSomewhere(ssb, where, win = window) {
-  return new Promise((resolve, reject) => {
-    // Listens for a new tab opening in the main window.
-    const tabListener = async ({ target: tab }) => {
-      cleanup();
-
-      await BrowserTestUtils.browserLoaded(
-        tab.linkedBrowser,
-        true,
-        uri => uri != "about:blank"
-      );
-
-      if (where != "tab") {
-        Assert.ok(
-          false,
-          `Did not expect ${tab.linkedBrowser.currentURI.spec} to load in a new tab.`
-        );
-        BrowserTestUtils.removeTab(tab);
-        reject(new Error("Page unexpectedly loaded in a new tab."));
-        return;
-      }
-      Assert.ok(
-        true,
-        `${tab.linkedBrowser.currentURI.spec} loaded in a new tab as expected.`
-      );
-      resolve(tab);
-    };
-    win.gBrowser.tabContainer.addEventListener("TabOpen", tabListener);
-
-    // Listens for new top-level windows.
-    const winObserver = async (domwin, topic) => {
-      if (topic != "domwindowopened") {
-        return;
-      }
-
-      cleanup();
-
-      await BrowserTestUtils.waitForEvent(
-        domwin,
-        "load",
-        uri => uri != "about:blank"
-      );
-
-      if (where != "window") {
-        Assert.ok(false, `Did not expect a new ${domwin.location} to open.`);
-        await BrowserTestUtils.closeWindow(domwin);
-        reject(new Error("New window unexpectedly opened."));
-        return;
-      }
-      Assert.ok(true, `${domwin.location} opened as expected.`);
-      resolve(domwin);
-    };
-    Services.ww.registerNotification(winObserver);
-
-    const ssbListener = () => {
-      cleanup();
-
-      if (where != "ssb") {
-        Assert.ok(
-          false,
-          `Did not expect ${
-            getBrowser(ssb).currentURI.spec
-          } to load in the ssb window.`
-        );
-        reject(new Error("Page unexpectedly loaded in the ssb window."));
-        return;
-      }
-      Assert.ok(
-        true,
-        `${
-          getBrowser(ssb).currentURI.spec
-        } loaded in the ssb window as expected.`
-      );
-      resolve();
-    };
-    getBrowser(ssb).addEventListener("SSBLoad", ssbListener);
-
-    // Makes sure that no notifications fire after the test is done.
-    const cleanup = () => {
-      win.gBrowser.tabContainer.removeEventListener("TabOpen", tabListener);
-      Services.ww.unregisterNotification(winObserver);
-      getBrowser(ssb).removeEventListener("SSBLoad", ssbListener);
-    };
-  });
-}
-
-/**
- * Waits for a load to occur in the ssb window but rejects if a new tab or
- * window get opened.
- */
-function expectSSBLoad(ssb, win = window) {
-  return expectLoadSomewhere(ssb, "ssb", win);
-}
-
-/**
- * Waits for a new tab to be opened and loaded. Rejects if a new window is
- * opened or the ssb loads something before. Resolves with the new loaded tab.
- */
-function expectTabLoad(ssb, win = window) {
-  return expectLoadSomewhere(ssb, "tab", win);
-}
-
-/**
- * Waits for a new window to be opened and loaded. Rejects if a new tab is
- * opened or the ssb loads something before. Resolves with the new loaded
- * window.
- */
-function expectWindowOpen(ssb, win = window) {
-  return expectLoadSomewhere(ssb, "window", win);
-}
-
-add_task(async () => {
-  let list = await SiteSpecificBrowserService.list();
-  Assert.equal(
-    list.length,
-    0,
-    "Should be no installed SSBs at the start of a test."
-  );
-});
-
-registerCleanupFunction(async () => {
-  let list = await SiteSpecificBrowserService.list();
-  Assert.equal(
-    list.length,
-    0,
-    "Should be no installed SSBs at the end of a test."
-  );
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/site1/allhost.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<meta charset="utf-8">
-<!-- This page links to a manifest that sets the scope to the entire host. -->
-<link rel="manifest" href="allhost.json">
-</head>
-<body>
-<p><a id="site1" href="../site1/final.html">Site 1</a></p>
-<p><a id="site2" href="../site2/final.html">Site 2</a></p>
-</body>
-</html>
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/site1/allhost.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "scope": "/"
-}
\ No newline at end of file
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/site1/bad.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<meta charset="utf-8">
-<!-- This page links to a manifest with an invalid scope. The manifest will
-     just be ignored in this case. -->
-<link rel="manifest" href="bad.json">
-</head>
-<body>
-<p><a id="site1" href="../site1/final.html">Site 1</a></p>
-<p><a id="site2" href="../site2/final.html">Site 2</a></p>
-</body>
-</html>
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/site1/bad.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "scope": "/foo/bar"
-}
\ No newline at end of file
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/site1/empty.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<meta charset="utf-8">
-<!-- This page links to an empty manifest. The default scope is the current
-     directory -->
-<link rel="manifest" href="empty.json">
-</head>
-<body>
-<p><a id="site1" href="../site1/final.html">Site 1</a></p>
-<p><a id="site2" href="../site2/final.html">Site 2</a></p>
-</body>
-</html>
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/site1/empty.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{}
\ No newline at end of file
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/site1/final.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<meta charset="utf-8">
-</head>
-<body>
-<p>Landing page</p>
-</body>
-</html>
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/site1/simple.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<meta charset="utf-8">
-<!-- This page has no linked manifest. A missing manifest is treated as the same
-     as an empty manifest where the default scope is the current directory -->
-</head>
-<body>
-<p><a id="site1" href="../site1/final.html">Site 1</a></p>
-<p><a id="site2" href="../site2/final.html">Site 2</a></p>
-</body>
-</html>
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/site2/final.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<meta charset="utf-8">
-</head>
-<body>
-<p>Landing page</p>
-</body>
-</html>
deleted file mode 100644
--- a/browser/components/ssb/tests/browser/test_page.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<title>Test site</title>
-<meta charset="utf-8">
-<script type="text/javascript">
-function initialize() {
-  let target = window.location.hash;
-  if (target.length < 2) {
-    return;
-  }
-  target = target.substring(1);
-
-  let anchor = document.getElementById("direct");
-  anchor.href = target;
-
-  anchor = document.getElementById("new-tab");
-  anchor.href = target;
-
-  anchor = document.getElementById("new-window");
-  anchor.href = target;
-
-  anchor = document.getElementById("window-open");
-  anchor.onclick = (e) => {
-    window.open(target, "foo", "height=300,width=400");
-    e.preventDefault();
-  };
-
-  anchor = document.getElementById("window-location");
-  anchor.onclick = (e) => {
-    window.location = target;
-    e.preventDefault();
-  };
-}
-
-window.addEventListener("load", initialize, true);
-</script>
-</head>
-<body>
-<p><a id="direct">Direct link</a></p>
-<p><a id="new-tab" target="_blank">New tab link</a></p>
-<p><a id="new-window" target="foo">New window link</a></p>
-<p><a id="window-open" href="#">window.open call</a></p>
-<p><a id="window-location" href="#">window.location manipulation</a></p>
-</body>
-</html>
deleted file mode 100644
--- a/browser/components/ssb/tests/xpcshell/head.js
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const { SiteSpecificBrowser, SiteSpecificBrowserService } = ChromeUtils.import(
-  "resource:///modules/SiteSpecificBrowserService.jsm"
-);
-const { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
-
-const ICON16 =
-  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAADUExURUdwTIL60tIAAAABdFJOUwBA5thmAAAAC0lEQVQIHWMgEQAAADAAAQrnSBQAAAAASUVORK5CYII=";
-const ICON32 =
-  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAADUExURUdwTIL60tIAAAABdFJOUwBA5thmAAAAC0lEQVQIHWMY5AAAAKAAAZearVIAAAAASUVORK5CYII=";
-const ICON48 =
-  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAADUExURUdwTIL60tIAAAABdFJOUwBA5thmAAAADElEQVQYGWMYBVQFAAFQAAHUa/NpAAAAAElFTkSuQmCC";
-const ICON96 =
-  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgAQMAAADYVuV7AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAADUExURUdwTIL60tIAAAABdFJOUwBA5thmAAAAEUlEQVQYGWMYBaNgFIyCYQoABOAAAZ11NUsAAAAASUVORK5CYII=";
-const ICON128 =
-  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACAAQMAAAD58POIAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAADUExURUdwTIL60tIAAAABdFJOUwBA5thmAAAAGElEQVQYGWMYBaNgFIyCUTAKRsEooDMAAAiAAAE2cKqmAAAAAElFTkSuQmCC";
-const ICON256 =
-  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAAA1BMVEVHcEyC+tLSAAAAAXRSTlMAQObYZgAAAB9JREFUGBntwQENAAAAwiD7p34ON2AAAAAAAAAAAOcCIQAAAfWivQQAAAAASUVORK5CYII=";
-
-XPCOMUtils.defineLazyModuleGetters(this, {
-  ManifestProcessor: "resource://gre/modules/ManifestProcessor.jsm",
-  KeyValueService: "resource://gre/modules/kvstore.jsm",
-  OS: "resource://gre/modules/osfile.jsm",
-  AppConstants: "resource://gre/modules/AppConstants.jsm",
-});
-
-let xreDirProvider = Cc["@mozilla.org/xre/directory-provider;1"].getService(
-  Ci.nsIXREDirProvider
-);
-
-const SSB_STORE_PREFIX = "ssb:";
-
-const uri = spec => Services.io.newURI(spec);
-const storeKey = id => SSB_STORE_PREFIX + id;
-
-let gProfD = do_get_profile();
-let gSSBData = gProfD.clone();
-gSSBData.append("ssb");
-
-Services.prefs.setBoolPref("browser.ssb.enabled", true);
-Services.prefs.setBoolPref("browser.ssb.osintegration", false);
-
-async function getKVStore() {
-  await OS.File.makeDir(gSSBData.path);
-  return KeyValueService.getOrCreate(gSSBData.path, "ssb");
-}
-
-function parseManifest(doc, manifest = {}) {
-  return ManifestProcessor.process({
-    jsonText: JSON.stringify(manifest),
-    manifestURL: new URL("/manifest.json", doc),
-    docURL: doc,
-  });
-}
-
-async function storeSSB(store, id, manifest, config = {}) {
-  return store.put(
-    storeKey(id),
-    JSON.stringify({
-      manifest,
-      config,
-    })
-  );
-}
deleted file mode 100644
--- a/browser/components/ssb/tests/xpcshell/test_empty.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Basic check. There should be no SSBs in an empty profile.
-add_task(async () => {
-  let ssbs = await SiteSpecificBrowserService.list();
-  Assert.equal(ssbs.length, 0);
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/xpcshell/test_icons.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function icons() {
-  let ssb = await SiteSpecificBrowser.createFromManifest(
-    parseManifest("https://www.mozilla.org/", {
-      icons: [
-        {
-          src: "data:b",
-          sizes: "24x24",
-        },
-        {
-          src: "data:a",
-          sizes: "16x16 32x32",
-        },
-        {
-          src: "data:c",
-          sizes: "any",
-        },
-        {
-          src: "data:d",
-          sizes: "128x128",
-        },
-      ],
-    })
-  );
-
-  Assert.equal(ssb.getIcon(1).src, "data:a");
-  Assert.equal(ssb.getIcon(15).src, "data:a");
-  Assert.equal(ssb.getIcon(16).src, "data:a");
-  Assert.equal(ssb.getIcon(17).src, "data:b");
-  Assert.equal(ssb.getIcon(23).src, "data:b");
-  Assert.equal(ssb.getIcon(24).src, "data:b");
-  Assert.equal(ssb.getIcon(25).src, "data:a");
-  Assert.equal(ssb.getIcon(31).src, "data:a");
-  Assert.equal(ssb.getIcon(32).src, "data:a");
-  Assert.equal(ssb.getIcon(33).src, "data:d");
-  Assert.equal(ssb.getIcon(127).src, "data:d");
-  Assert.equal(ssb.getIcon(128).src, "data:d");
-  Assert.equal(ssb.getIcon(129).src, "data:c");
-  Assert.equal(ssb.getIcon(5000).src, "data:c");
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/xpcshell/test_install.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that installing adds it to the store.
-add_task(async () => {
-  Services.prefs.setBoolPref("browser.ssb.osintegration", true);
-
-  let ssb = await SiteSpecificBrowser.createFromManifest(
-    parseManifest("https://www.mozilla.org/", {
-      icons: [
-        {
-          src: ICON32,
-          sizes: "32x32",
-        },
-        {
-          src: ICON48,
-          sizes: "48x48",
-        },
-        {
-          src: ICON128,
-          sizes: "128x128",
-        },
-      ],
-    })
-  );
-  await ssb.install();
-
-  let ssbs = await SiteSpecificBrowserService.list();
-  Assert.equal(ssbs.length, 1);
-  Assert.equal(ssbs[0], ssb);
-
-  let kvstore = await getKVStore();
-  Assert.ok(await kvstore.has(storeKey(ssb.id)));
-
-  // Don't want to rely on the structure too much, just make sure it looks sane.
-  let data = JSON.parse(await kvstore.get(`ssb:${ssb.id}`));
-  Assert.ok("manifest" in data);
-  Assert.ok("config" in data);
-
-  if (AppConstants.platform == "win") {
-    // Check that the shortcut is made and destroyed.
-    let link = Services.dirsvc.get("Desk", Ci.nsIFile);
-    link.append("www.mozilla.org.lnk");
-
-    Assert.ok(link.isFile());
-
-    let icon = gSSBData.clone();
-    icon.append(ssb.id);
-    icon.append("icon.ico");
-
-    Assert.ok(icon.isFile());
-
-    await ssb.uninstall();
-    Assert.ok(!link.exists());
-    let dir = gSSBData.clone();
-    dir.append(ssb.id);
-    Assert.ok(!dir.exists());
-  }
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/xpcshell/test_manifest.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function empty_manifest() {
-  let ssb = await SiteSpecificBrowser.createFromManifest(
-    parseManifest("https://www.mozilla.org/")
-  );
-
-  Assert.equal(ssb.startURI.spec, "https://www.mozilla.org/");
-
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/")));
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo")));
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/bar")));
-  Assert.ok(!ssb.canLoad(uri("http://www.mozilla.org/")));
-  Assert.ok(!ssb.canLoad(uri("https://test.mozilla.org/")));
-});
-
-add_task(async function manifest_with_scope() {
-  let ssb = await SiteSpecificBrowser.createFromManifest(
-    parseManifest("https://www.mozilla.org/foo/bar", {
-      scope: "https://www.mozilla.org/foo",
-    })
-  );
-
-  Assert.equal(ssb.startURI.spec, "https://www.mozilla.org/foo/bar");
-
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo")));
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo/bar")));
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo/baz")));
-
-  // Note: scopes are simple path prefixes.
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/food")));
-
-  Assert.ok(!ssb.canLoad(uri("https://www.mozilla.org/")));
-  Assert.ok(!ssb.canLoad(uri("https://www.mozilla.org/bar")));
-  Assert.ok(!ssb.canLoad(uri("http://www.mozilla.org/")));
-  Assert.ok(!ssb.canLoad(uri("https://test.mozilla.org/")));
-});
-
-add_task(async function manifest_with_start_url() {
-  let ssb = await SiteSpecificBrowser.createFromManifest(
-    parseManifest("https://www.mozilla.org/foo/bar", {
-      start_url: "https://www.mozilla.org/foo/",
-    })
-  );
-
-  Assert.equal(ssb.startURI.spec, "https://www.mozilla.org/foo/");
-
-  // scope should be "https://www.mozilla.org/foo/"
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo/bar")));
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo/baz")));
-
-  Assert.ok(!ssb.canLoad(uri("https://www.mozilla.org/foo")));
-  Assert.ok(!ssb.canLoad(uri("https://www.mozilla.org/")));
-  Assert.ok(!ssb.canLoad(uri("https://www.mozilla.org/bar")));
-  Assert.ok(!ssb.canLoad(uri("http://www.mozilla.org/")));
-  Assert.ok(!ssb.canLoad(uri("https://test.mozilla.org/")));
-});
-
-add_task(async function update_manifest() {
-  let ssb = await SiteSpecificBrowser.createFromManifest(
-    parseManifest("https://www.mozilla.org/foo/bar/bas", {
-      start_url: "https://www.mozilla.org/foo/bar/bas",
-      scope: "https://www.mozilla.org/foo/bar/",
-    })
-  );
-
-  Assert.equal(ssb.startURI.spec, "https://www.mozilla.org/foo/bar/bas");
-
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo/bar/")));
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo/bar/foo")));
-
-  Assert.ok(!ssb.canLoad(uri("https://www.mozilla.org/foo")));
-  Assert.ok(!ssb.canLoad(uri("https://www.mozilla.org/foo/bar")));
-
-  await ssb.updateFromManifest(
-    parseManifest("https://www.mozilla.org/foo/bar/bas", {
-      start_url: "https://www.mozilla.org/foo/bar/bas",
-      scope: "https://www.mozilla.org/foo/",
-    })
-  );
-
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo/bar/")));
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo/bar/foo")));
-
-  Assert.ok(!ssb.canLoad(uri("https://www.mozilla.org/foo")));
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/foo/bar")));
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/xpcshell/test_too_new.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// A database that is too new should be wiped.
-add_task(async () => {
-  let kvstore = await getKVStore();
-  kvstore.put(
-    "_meta",
-    JSON.stringify({
-      version: 1000,
-    })
-  );
-
-  storeSSB(kvstore, "a", parseManifest("https://www.mozilla.org/"), {});
-  storeSSB(kvstore, "b", parseManifest("https://www.microsoft.com/"), {});
-
-  let ssbs = await SiteSpecificBrowserService.list();
-  Assert.equal(ssbs.length, 0);
-
-  let meta = JSON.parse(await kvstore.get("_meta"));
-  Assert.equal(meta.version, 1);
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/xpcshell/test_uninstall.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that uninstalling removes from the store.
-add_task(async () => {
-  let kvstore = await getKVStore();
-  kvstore.put(
-    "_meta",
-    JSON.stringify({
-      version: 1,
-    })
-  );
-
-  storeSSB(kvstore, "a", parseManifest("https://www.mozilla.org/"), {});
-
-  let ssb = await SiteSpecificBrowser.load("a");
-
-  let ssbs = await SiteSpecificBrowserService.list();
-  Assert.equal(ssbs.length, 1);
-  Assert.equal(ssbs[0], ssb);
-
-  Assert.ok(ssb.canLoad(uri("https://www.mozilla.org/test/")));
-  Assert.ok(!ssb.canLoad(uri("https://www.microsoft.com/test/")));
-
-  await ssb.uninstall();
-
-  ssbs = await SiteSpecificBrowserService.list();
-  Assert.equal(ssbs.length, 0);
-
-  Assert.ok(!(await kvstore.has(storeKey("a"))));
-});
deleted file mode 100644
--- a/browser/components/ssb/tests/xpcshell/xpcshell.ini
+++ /dev/null
@@ -1,12 +0,0 @@
-[DEFAULT]
-head = head.js
-firefox-appdir = browser
-
-[test_empty.js]
-[test_icons.js]
-[test_install.js]
-[test_manifest.js]
-[test_too_new.js]
-skip-if = tsan # Times out, bug 1674773
-[test_uninstall.js]
-skip-if = tsan # Times out, bug 1674773
--- a/browser/modules/PageActions.jsm
+++ b/browser/modules/PageActions.jsm
@@ -31,21 +31,16 @@ ChromeUtils.defineModuleGetter(
   "BinarySearch",
   "resource://gre/modules/BinarySearch.jsm"
 );
 ChromeUtils.defineModuleGetter(
   this,
   "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm"
 );
-ChromeUtils.defineModuleGetter(
-  this,
-  "SiteSpecificBrowserService",
-  "resource:///modules/SiteSpecificBrowserService.jsm"
-);
 
 const ACTION_ID_BOOKMARK = "bookmark";
 const ACTION_ID_PIN_TAB = "pinTab";
 const ACTION_ID_BOOKMARK_SEPARATOR = "bookmarkSeparator";
 const ACTION_ID_BUILT_IN_SEPARATOR = "builtInSeparator";
 const ACTION_ID_TRANSIENT_SEPARATOR = "transientSeparator";
 
 const PREF_PERSISTED_ACTIONS = "browser.pageActions.persistedActions";
@@ -1287,30 +1282,16 @@ if (Services.prefs.getBoolPref("identity
     onSubviewShowing(panelViewNode) {
       browserPageActions(panelViewNode).sendToDevice.onShowingSubview(
         panelViewNode
       );
     },
   });
 }
 
-if (SiteSpecificBrowserService.isEnabled) {
-  gBuiltInActions.push({
-    id: "launchSSB",
-    // Hardcoded for now. Localization tracked in bug 1602528.
-    title: "Use This Site in App Mode",
-    onLocationChange(browserWindow) {
-      browserPageActions(browserWindow).launchSSB.updateState();
-    },
-    onCommand(event, buttonNode) {
-      browserPageActions(buttonNode).launchSSB.onCommand(event, buttonNode);
-    },
-  });
-}
-
 // share URL
 if (AppConstants.platform == "macosx") {
   gBuiltInActions.push({
     id: "shareURL",
     panelFluentID: "page-action-share-url-panel",
     urlbarFluentID: "page-action-share-url-urlbar",
     onShowingInPanel(buttonNode) {
       browserPageActions(buttonNode).shareURL.onShowingInPanel(buttonNode);
deleted file mode 100644
--- a/browser/themes/shared/install-ssb.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
-  <path fill="context-fill" fill-opacity="context-fill-opacity" d="M15 2h-1V1a1 1 0 0 0-2 0v1h-1a1 1 0 0 0 0 2h1v1a1 1 0 0 0 2 0V4h1a1 1 0 0 0 0-2z"/>
-  <path fill="context-fill" fill-opacity="context-fill-opacity" d="M13 7a1 1 0 0 0-1 1v5H3V4h5a1 1 0 0 0 0-2H2a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1V8a1 1 0 0 0-1-1z"/>
-</svg>
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -287,10 +287,9 @@
   skin/classic/browser/places/folder.svg                       (../shared/places/folder.svg)
   skin/classic/browser/places/folder-smart.svg                 (../shared/places/folder-smart.svg)
   skin/classic/browser/places/history.svg                      (../shared/places/history.svg)
   skin/classic/browser/places/tag.svg                          (../shared/places/tag.svg)
   skin/classic/browser/places/tree-icons.css                   (../shared/places/tree-icons.css)
   skin/classic/browser/privatebrowsing/aboutPrivateBrowsing.css (../shared/privatebrowsing/aboutPrivateBrowsing.css)
   skin/classic/browser/privatebrowsing/favicon.svg             (../shared/privatebrowsing/favicon.svg)
   skin/classic/browser/privatebrowsing/private-browsing.svg    (../shared/privatebrowsing/private-browsing.svg)
-  skin/classic/browser/install-ssb.svg                         (../shared/install-ssb.svg)
   skin/classic/browser/critical.svg                            (../shared/icons/critical.svg)
--- a/browser/themes/shared/menupanel.inc.css
+++ b/browser/themes/shared/menupanel.inc.css
@@ -172,14 +172,8 @@ toolbarpaletteitem[place="palette"] > #b
 
 #appMenu-library-downloads-button {
   list-style-image: url("chrome://browser/skin/downloads/download-icons.svg#arrow-with-bar");
 }
 
 #appMenu-library-downloads-show-button {
   list-style-image: url("chrome://browser/skin/folder.svg");
 }
-
-.panel-subview-body .ssb-uninstall > .toolbarbutton-icon {
-  list-style-image: url("chrome://global/skin/icons/close.svg");
-  -moz-context-properties: fill, fill-opacity;
-  fill-opacity: 0;
-}
--- a/browser/themes/shared/urlbar-searchbar.inc.css
+++ b/browser/themes/shared/urlbar-searchbar.inc.css
@@ -468,21 +468,16 @@
   min-width: 11px;
   min-height: 11px;
 }
 
 #pageActionActivatedActionPanel[actionID="pocket"] {
   --arrowpanel-background: #fbfbfb;
 }
 
-#pageAction-panel-launchSSB,
-#pageAction-urlbar-launchSSB {
-  list-style-image: url("chrome://browser/skin/install-ssb.svg");
-}
-
 /* URL bar and page action buttons */
 
 #page-action-buttons {
   -moz-box-align: center;
 }
 
 #pageActionSeparator {
   /* This draws the separator the same way that #urlbar-label-box draws its