Merge mozilla-central to beta. a=merge, l10n=me on a CLOSED TREE
authorSebastian Hengst <archaeopteryx@coole-files.de>
Fri, 09 Mar 2018 01:43:10 +0200
changeset 462214 e18b07e250b1a49de41b3d738d74ea39f5504c0f
parent 461873 9b028aef17cb86ef1ca4a291ed33c92634f7c190 (current diff)
parent 462213 55d91695f4bb951c224005155baef054a786c1f7 (diff)
child 462215 edafc2f99aadad753d425317b84b14beaad96d39
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone60.0
Merge mozilla-central to beta. a=merge, l10n=me on a CLOSED TREE
browser/base/content/newtab/alternativeDefaultSites.json
browser/base/content/newtab/cells.js
browser/base/content/newtab/customize.js
browser/base/content/newtab/drag.js
browser/base/content/newtab/dragDataHelper.js
browser/base/content/newtab/drop.js
browser/base/content/newtab/dropPreview.js
browser/base/content/newtab/dropTargetShim.js
browser/base/content/newtab/grid.js
browser/base/content/newtab/newTab.css
browser/base/content/newtab/newTab.js
browser/base/content/newtab/newTab.xhtml
browser/base/content/newtab/page.js
browser/base/content/newtab/search.js
browser/base/content/newtab/sites.js
browser/base/content/newtab/transformations.js
browser/base/content/newtab/undo.js
browser/base/content/newtab/updater.js
browser/base/content/test/newtab/.eslintrc.js
browser/base/content/test/newtab/browser.ini
browser/base/content/test/newtab/browser_newtab_1188015.js
browser/base/content/test/newtab/browser_newtab_background_captures.js
browser/base/content/test/newtab/browser_newtab_block.js
browser/base/content/test/newtab/browser_newtab_bug1271075.js
browser/base/content/test/newtab/browser_newtab_bug721442.js
browser/base/content/test/newtab/browser_newtab_bug722273.js
browser/base/content/test/newtab/browser_newtab_bug723102.js
browser/base/content/test/newtab/browser_newtab_bug723121.js
browser/base/content/test/newtab/browser_newtab_bug725996.js
browser/base/content/test/newtab/browser_newtab_bug734043.js
browser/base/content/test/newtab/browser_newtab_bug735987.js
browser/base/content/test/newtab/browser_newtab_bug752841.js
browser/base/content/test/newtab/browser_newtab_bug765628.js
browser/base/content/test/newtab/browser_newtab_bug876313.js
browser/base/content/test/newtab/browser_newtab_bug991111.js
browser/base/content/test/newtab/browser_newtab_bug991210.js
browser/base/content/test/newtab/browser_newtab_bug998387.js
browser/base/content/test/newtab/browser_newtab_disable.js
browser/base/content/test/newtab/browser_newtab_drag_drop.js
browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js
browser/base/content/test/newtab/browser_newtab_drop_preview.js
browser/base/content/test/newtab/browser_newtab_focus.js
browser/base/content/test/newtab/browser_newtab_fullscreen_focus.js
browser/base/content/test/newtab/browser_newtab_perwindow_private_browsing.js
browser/base/content/test/newtab/browser_newtab_reflow_load.js
browser/base/content/test/newtab/browser_newtab_search.js
browser/base/content/test/newtab/browser_newtab_undo.js
browser/base/content/test/newtab/browser_newtab_unpin.js
browser/base/content/test/newtab/browser_newtab_update.js
browser/base/content/test/newtab/content-reflows.js
browser/base/content/test/newtab/head.js
browser/base/content/test/newtab/searchEngine1x2xLogo.xml
browser/base/content/test/newtab/searchEngine1xLogo.xml
browser/base/content/test/newtab/searchEngine2xLogo.xml
browser/base/content/test/newtab/searchEngineFavicon.xml
browser/base/content/test/newtab/searchEngineNoLogo.xml
browser/components/search/test/browser_yahoo.js
browser/locales/en-US/chrome/browser/newTab.dtd
browser/locales/en-US/chrome/browser/newTab.properties
browser/themes/linux/newtab/newTab.css
browser/themes/osx/newtab/newTab.css
browser/themes/shared/newtab/close.png
browser/themes/shared/newtab/controls.svg
browser/themes/shared/newtab/newTab.inc.css
browser/themes/windows/newtab/newTab.css
devtools/client/framework/test/shared-head.js
devtools/client/framework/test/shared-redux-head.js
devtools/client/shared/frame-script-utils.js
dom/events/test/test_eventTimeStamp.html
dom/webidl/ChannelWrapper.webidl
dom/webidl/ChromeUtils.webidl
dom/webidl/DominatorTree.webidl
dom/webidl/HeapSnapshot.webidl
dom/webidl/InspectorUtils.webidl
dom/webidl/MatchGlob.webidl
dom/webidl/MatchPattern.webidl
dom/webidl/MozStorageAsyncStatementParams.webidl
dom/webidl/MozStorageStatementParams.webidl
dom/webidl/MozStorageStatementRow.webidl
dom/webidl/PrecompiledScript.webidl
dom/webidl/PromiseDebugging.webidl
dom/webidl/StructuredCloneHolder.webidl
dom/webidl/WebExtensionContentScript.webidl
dom/webidl/WebExtensionPolicy.webidl
gfx/2d/Box.h
gfx/harfbuzz/src/check-defs.sh
gfx/harfbuzz/src/hb-ot-cbdt-table.hh
gfx/src/nsCoordBox.h
layout/base/nsFrameManagerBase.h
mobile/android/base/java/org/mozilla/gecko/PresentationMediaPlayerManager.java
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationListenerTest.kt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressListenerTest.kt
services/sync/tests/unit/places_v10_from_v11.sqlite
services/sync/tests/unit/test_places_guid_downgrade.js
taskcluster/docker/firefox-snap/mime-handler.xml
taskcluster/docker/periodic_updates/.eslintrc.js
taskcluster/docker/periodic_updates/Dockerfile
taskcluster/docker/periodic_updates/README.md
taskcluster/docker/periodic_updates/runme.sh
taskcluster/docker/periodic_updates/scripts/genHPKPStaticPins.js
taskcluster/docker/periodic_updates/scripts/getHSTSPreloadList.js
taskcluster/docker/periodic_updates/scripts/periodic_file_updates.sh
taskcluster/taskgraph/transforms/task.py
testing/talos/talos/tests/devtools/addon/content/pages/custom/debugger/static/js/main.447c224f.js
testing/talos/talos/tests/devtools/addon/content/pages/custom/debugger/static/js/main.447c224f.js.map
testing/web-platform/meta/html/semantics/document-metadata/the-link-element/link-load-event.html.ini
testing/web-platform/meta/webdriver/tests/actions/key.py.ini
testing/web-platform/tests/common/css-paint-tests.js
third_party/rust/futures/FAQ.md
third_party/rust/futures/src/stack.rs
third_party/rust/futures/src/stream/mod.rs
third_party/rust/futures/src/task_impl/data.rs
third_party/rust/futures/src/task_impl/task_rc.rs
third_party/rust/futures/src/task_impl/unpark_mutex.rs
third_party/rust/futures/tests/support/mod.rs
toolkit/components/jsdownloads/moz.build
toolkit/components/jsdownloads/public/moz.build
toolkit/components/jsdownloads/public/mozIDownloadPlatform.idl
toolkit/components/jsdownloads/src/DownloadCore.jsm
toolkit/components/jsdownloads/src/DownloadHistory.jsm
toolkit/components/jsdownloads/src/DownloadIntegration.jsm
toolkit/components/jsdownloads/src/DownloadLegacy.js
toolkit/components/jsdownloads/src/DownloadList.jsm
toolkit/components/jsdownloads/src/DownloadPaths.jsm
toolkit/components/jsdownloads/src/DownloadPlatform.cpp
toolkit/components/jsdownloads/src/DownloadPlatform.h
toolkit/components/jsdownloads/src/DownloadStore.jsm
toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
toolkit/components/jsdownloads/src/Downloads.jsm
toolkit/components/jsdownloads/src/Downloads.manifest
toolkit/components/jsdownloads/src/moz.build
toolkit/components/jsdownloads/test/browser/.eslintrc.js
toolkit/components/jsdownloads/test/browser/browser.ini
toolkit/components/jsdownloads/test/browser/browser_DownloadPDFSaver.js
toolkit/components/jsdownloads/test/browser/head.js
toolkit/components/jsdownloads/test/browser/testFile.html
toolkit/components/jsdownloads/test/data/.eslintrc.js
toolkit/components/jsdownloads/test/data/empty.txt
toolkit/components/jsdownloads/test/data/source.txt
toolkit/components/jsdownloads/test/unit/.eslintrc.js
toolkit/components/jsdownloads/test/unit/common_test_Download.js
toolkit/components/jsdownloads/test/unit/head.js
toolkit/components/jsdownloads/test/unit/test_DownloadCore.js
toolkit/components/jsdownloads/test/unit/test_DownloadHistory.js
toolkit/components/jsdownloads/test/unit/test_DownloadIntegration.js
toolkit/components/jsdownloads/test/unit/test_DownloadLegacy.js
toolkit/components/jsdownloads/test/unit/test_DownloadList.js
toolkit/components/jsdownloads/test/unit/test_DownloadPaths.js
toolkit/components/jsdownloads/test/unit/test_DownloadStore.js
toolkit/components/jsdownloads/test/unit/test_Downloads.js
toolkit/components/jsdownloads/test/unit/test_PrivateTemp.js
toolkit/components/jsdownloads/test/unit/xpcshell.ini
toolkit/themes/shared/menu-check-active.svg
toolkit/themes/shared/menu-check-black.svg
toolkit/themes/shared/menu-check-hover.svg
--- a/.eslintignore
+++ b/.eslintignore
@@ -66,18 +66,16 @@ xpfe/**
 view/**
 
 # browser/ exclusions
 browser/app/**
 browser/branding/**/firefox-branding.js
 # Gzipped test file.
 browser/base/content/test/general/gZipOfflineChild.html
 browser/base/content/test/urlbar/file_blank_but_not_blank.html
-# New tab is likely to be replaced soon.
-browser/base/content/newtab/**
 # Test files that are really json not js, and don't need to be linted.
 browser/components/sessionstore/test/unit/data/sessionstore_valid.js
 browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
 # This file is split into two in order to keep it as a valid json file
 # for documentation purposes (policies.json) but to be accessed by the
 # code as a .jsm (schema.jsm)
 browser/components/enterprisepolicies/schemas/schema.jsm
 # generated & special files in cld2
@@ -375,16 +373,17 @@ testing/mochitest/**
 testing/modules/ajv-4.1.1.js
 testing/modules/sinon-2.3.2.js
 # octothorpe used for pref file comment causes parsing error
 testing/mozbase/mozprofile/tests/files/prefs_with_comments.js
 testing/talos/talos/scripts/jszip.min.js
 testing/talos/talos/startup_test/sessionrestore/profile/sessionstore.js
 testing/talos/talos/startup_test/sessionrestore/profile-manywindows/sessionstore.js
 testing/talos/talos/tests/canvasmark/**
+testing/talos/talos/tests/devtools/addon/content/pages/**
 testing/talos/talos/tests/dromaeo/**
 testing/talos/talos/tests/v8_7/**
 testing/talos/talos/tests/kraken/**
 # Runing Talos may extract data here, see bug 1435677.
 testing/talos/talos/tests/tp5n/**
 
 testing/web-platform/**
 testing/xpcshell/moz-http2/**
--- a/.gitignore
+++ b/.gitignore
@@ -71,16 +71,17 @@ parser/html/java/javaparser/
 
 # Local Gradle configuration properties.
 /local.properties
 
 # Python virtualenv artifacts.
 third_party/python/psutil/**/*.so
 third_party/python/psutil/**/*.pyd
 third_party/python/psutil/build/
+third_party/python/psutil/tmp/
 
 # Ignore chrome.manifest files from the devtools loader
 devtools/client/chrome.manifest
 devtools/shared/chrome.manifest
 
 # Ignore node_modules directories in devtools
 devtools/**/node_modules
 
--- a/.hgignore
+++ b/.hgignore
@@ -72,16 +72,17 @@
 
 # Local Gradle configuration properties.
 ^local.properties$
 
 # Python stuff installed at build time.
 ^third_party/python/psutil/.*\.so
 ^third_party/python/psutil/.*\.pyd
 ^third_party/python/psutil/build/
+^third_party/python/psutil/tmp/
 
 # Git repositories
 .git/
 
 # Ignore chrome.manifest files from the devtools loader
 ^devtools/client/chrome.manifest$
 ^devtools/shared/chrome.manifest$
 
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -51,17 +51,17 @@ dependencies = [
 [[package]]
 name = "audioipc"
 version = "0.2.1"
 dependencies = [
  "bincode 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)",
  "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -71,33 +71,33 @@ dependencies = [
 
 [[package]]
 name = "audioipc-client"
 version = "0.3.0"
 dependencies = [
  "audioipc 0.2.1",
  "cubeb-backend 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "audioipc-server"
 version = "0.2.2"
 dependencies = [
  "audioipc 0.2.1",
  "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -639,25 +639,25 @@ name = "fuchsia-zircon-sys"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "futures"
-version = "0.1.13"
+version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "futures-cpupool"
-version = "0.1.5"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fxhash"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1834,42 +1834,42 @@ dependencies = [
 ]
 
 [[package]]
 name = "tokio-core"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tokio-io"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tokio-uds"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2029,16 +2029,17 @@ name = "webdriver"
 version = "0.34.0"
 dependencies = [
  "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender"
 version = "0.57.0"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2273,18 +2274,18 @@ dependencies = [
 "checksum euclid 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2744c002882c67d0f6d6e8cfdf16eae729dc27744d312745132e62218b7de5c"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ebc04f19019fff1f2d627b5581574ead502f80c48c88900575a46e0840fe5d0"
 "checksum freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "398b8a11884898184d55aca9806f002b3cf68f0e860e0cbb4586f834ee39b0e7"
 "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
 "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
 "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
-"checksum futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "55f0008e13fc853f79ea8fc86e931486860d4c4c156cdffb59fa5f7fa833660a"
-"checksum futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a283c84501e92cade5ea673a2a7ca44f71f209ccdd302a3e0896f50083d2c5ff"
+"checksum futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0bab5b5e94f5c31fc764ba5dd9ad16568aae5d4825538c01d6bca680c9bf94a7"
+"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
 "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
 "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
 "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum gl_generator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f5c19cde55637681450c92f7a05ea16c78e2b6d0587e601ec1ebdab6960854b"
 "checksum gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "959c818d9bbe9f7b7db55dce0bc44673c4da4f4ee122536c40550f984c3b8017"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
 "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<blocklist lastupdate="1520338780397" xmlns="http://www.mozilla.org/2006/addons-blocklist">
+<blocklist lastupdate="1520358450708" xmlns="http://www.mozilla.org/2006/addons-blocklist">
   <emItems>
     <emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="i1211" id="flvto@hotger.com">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="1"/>
@@ -2214,16 +2214,20 @@
     <emItem blockID="48b14881-5f6b-4e48-afc5-3d9a7fae26a3" id="/{0c9970a2-6874-483b-a486-2296cfe251c2}|{01c9a4a4-06dd-426b-9500-2ea6fe841b88}|{1c981c7c-30e0-4ed2-955d-6b370e0a9d19}|{2aa275f8-fabc-4766-95b2-ecfc73db310b}|{2cac0be1-10a2-4a0d-b8c5-787837ea5955}|{2eb66f6c-94b3-44f5-9de2-22371236ec99}|{2f8aade6-8717-4277-b8b1-55172d364903}|{3c27c34f-8775-491a-a1c9-fcb15beb26d3}|{3f4dea3e-dbfc-428f-a88b-36908c459e20}|{3f4191fa-8f16-47d2-9414-36bfc9e0c2bf}|{4c140bc5-c2ad-41c3-a407-749473530904}|{05a21129-af2a-464c-809f-f2df4addf209}|{5da81d3d-5db1-432a-affc-4a2fe9a70749}|{5f4e63e4-351f-4a21-a8e5-e50dc72b5566}|{7c1df23b-1fd8-42b9-8752-71fff2b979de}|{7d5e24a1-7bef-4d09-a952-b9519ec00d20}|{7d932012-b4dd-42cc-8a78-b15ca82d0e61}|{7f8bc48d-1c7c-41a0-8534-54adc079338f}|{8a61507d-dc2f-4507-a9b7-7e33b8cbc31b}|{09c8fa16-4eec-4f78-b19d-9b24b1b57e1e}|{9ce2a636-0e49-4b8e-ad17-d0c156c963b0}|{11df9391-dba5-4fe2-bd48-37a9182b796d}|{23c65153-c21e-430a-a2dc-0793410a870d}|{36a4269e-4eef-4538-baea-9dafbf6a8e2f}|{37f8e483-c782-40ed-82e9-36f101b9e41f}|{63df223d-51cf-4f76-aad8-bbc94c895ed2}|{72c1ca96-c05d-46a7-bce1-c507ec3db4ea}|{76ce213c-8e57-4a14-b60a-67a5519bd7a7}|{79db6c96-d65a-4a64-a892-3d26bd02d2d9}|{81ac42f3-3d17-4cff-85af-8b7f89c8826b}|{83d38ac3-121b-4f28-bf9c-1220bd3c643b}|{86d98522-5d42-41d5-83c2-fc57f260a3d9}|{0111c475-01e6-42ea-a9b4-27bed9eb6092}|{214cb48a-ce31-4e48-82cf-a55061f1b766}|{216e0bcc-8a23-4069-8b63-d9528b437258}|{226b0fe6-f80f-48f1-9d8d-0b7a1a04e537}|{302ef84b-2feb-460e-85ca-f5397a77aa6a}|{408a506b-2336-4671-a490-83a1094b4097}|{419be4e9-c981-478e-baa0-937cf1eea1e8}|{0432b92a-bfcf-41b9-b5f0-df9629feece1}|{449e185a-dd91-4f7b-a23a-bbf6c1ca9435}|{591d1b73-5eae-47f4-a41f-8081d58d49bf}|{869b5825-e344-4375-839b-085d3c09ab9f}|{919fed43-3961-48d9-b0ef-893054f4f6f1}|{01166e60-d740-440c-b640-6bf964504b3c}|{2134e327-8060-441c-ba68-b167b82ff5bc}|{02328ee7-a82b-4983-a5f7-d0fc353698f0}|{6072a2a8-f1bc-4c9c-b836-7ac53e3f51e4}|{28044ca8-8e90-435e-bc63-a757af2fb6be}|{28092fa3-9c52-4a41-996d-c43e249c5f08}|{31680d42-c80d-4f8a-86d3-cd4930620369}|{92111c8d-0850-4606-904a-783d273a2059}|{446122cd-cd92-4d0c-9426-4ee0d28f6dca}|{829827cd-03be-4fed-af96-dd5997806fb4}|{4479446e-40f3-48af-ab85-7e3bb4468227}|{9263519f-ca57-4178-b743-2553a40a4bf1}|{71639610-9cc3-47e0-86ed-d5b99eaa41d5}|{84406197-6d37-437c-8d82-ae624b857355}|{93017064-dfd4-425e-a700-353f332ede37}|{a0ab16af-3384-4dbe-8722-476ce3947873}|{a0c54bd8-7817-4a40-b657-6dc7d59bd961}|{a2de96bc-e77f-4805-92c0-95c9a2023c6a}|{a3fbc8be-dac2-4971-b76a-908464cfa0e0}|{a42e5d48-6175-49e3-9e40-0188cde9c5c6}|{a893296e-5f54-43f9-a849-f12dcdee2c98}|{ac296b47-7c03-486f-a1d6-c48b24419749}|{b26bf964-7aa6-44f4-a2a9-d55af4b4eec0}|{be981b5e-1d9d-40dc-bd4f-47a7a027611c}|{be37931c-af60-4337-8708-63889f36445d}|{bfd92dfd-b293-4828-90c1-66af2ac688e6}|{c5cf4d08-0a33-4aa3-a40d-d4911bcc1da7}|{c488a8f5-ea3d-408d-809e-44e82c06ad9d}|{c661c2dc-00f9-4dc1-a9f6-bb2b7e1a4f8d}|{cd28aa38-d2f1-45a3-96c3-6cfd4702ef51}|{cd89045b-2e06-46bb-9e34-48e8799e5ef2}|{cf9d96ff-5997-439a-b32b-98214c621eee}|{d14acee6-f32b-4aa3-a802-6616003fc6a8}|{d97223b8-44e5-46c7-8ab5-e1d8986daf44}|{ddae89bd-6793-45d8-8ec9-7f4fb7212378}|{de3b1909-d4da-45e9-8da5-7d36a30e2fc6}|{df09f268-3c92-49db-8c31-6a25a6643896}|{e5bc3951-c837-4c98-9643-3c113fc8cf5e}|{e9ccb1f2-a8ba-4346-b43b-0d5582bce414}|{e341ed12-a703-47fe-b8dd-5948c38070e4}|{e2139287-2b0d-4f54-b3b1-c9a06c597223}|{ed352072-ddf0-4cb4-9cb6-d8aa3741c2de}|{f0b809eb-be22-432f-b26f-b1cadd1755b9}|{f1bce8e4-9936-495b-bf48-52850c7250ab}|{f01c3add-dc6d-4f35-a498-6b4279aa2ffa}|{f9e1ad25-5961-4cc5-8d66-5496c438a125}|{f4262989-6de0-4604-918f-663b85fad605}|{fc0d55bd-3c50-4139-9409-7df7c1114a9d}/">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
     <emItem blockID="0cd723fe-d33d-43a0-b84f-7a3cad253212" id="{42baa93e-0cff-4289-b79e-6ae88df668c4}">
       <prefs/>
       <versionRange minVersion="0" maxVersion="*" severity="3"/>
     </emItem>
+    <emItem blockID="f58729ec-f93c-41d9-870d-dd9c9fd811b6" id="/^(addon@fasterweb\.com|\{5f398d3f-25db-47f5-b422-aa2364ff6c0b\}|addon@fasterp\.com|addon@calculator)$/">
+      <prefs/>
+      <versionRange minVersion="0" maxVersion="*" severity="3"/>
+    </emItem>
   </emItems>
   <pluginItems>
     <pluginItem blockID="p332">
       <match exp="libflashplayer\.so" name="filename"/>
       <match exp="^Shockwave Flash 11.(0|1) r[0-9]{1,3}$" name="description"/>
       <infoURL>https://get.adobe.com/flashplayer/</infoURL>
       <versionRange severity="0" vulnerabilitystatus="1">
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -71,17 +71,19 @@ pref("extensions.geckoProfiler.getSymbol
 pref("extensions.geckoProfiler.getSymbolRules", "localBreakpad,remoteBreakpad");
 #endif
 
 
 // Add-on content security policies.
 pref("extensions.webextensions.base-content-security-policy", "script-src 'self' https://* moz-extension: blob: filesystem: 'unsafe-eval' 'unsafe-inline'; object-src 'self' https://* moz-extension: blob: filesystem:;");
 pref("extensions.webextensions.default-content-security-policy", "script-src 'self'; object-src 'self';");
 
-#ifdef XP_WIN
+#if defined(XP_WIN)
+pref("extensions.webextensions.remote", true);
+#elif defined(XP_MACOSX) && !defined(RELEASE_OR_BETA)
 pref("extensions.webextensions.remote", true);
 #endif
 
 // Extensions that should not be flagged as legacy in about:addons
 pref("extensions.legacy.exceptions", "{972ce4c6-7e08-4474-a285-3208198ce6fd},testpilot@cliqz.com,@testpilot-containers,jid1-NeEaf3sAHdKHPA@jetpack,@activity-streams,pulse@mozilla.com,@testpilot-addon,@min-vid,tabcentertest1@mozilla.com,snoozetabs@mozilla.com,speaktome@mozilla.com,hoverpad@mozilla.com");
 
 // Require signed add-ons by default
 pref("xpinstall.signatures.required", true);
@@ -394,18 +396,17 @@ pref("browser.search.order.3",          
 
 // Market-specific search defaults
 pref("browser.search.geoSpecificDefaults", true);
 pref("browser.search.geoSpecificDefaults.url", "https://search.services.mozilla.com/1/%APP%/%VERSION%/%CHANNEL%/%LOCALE%/%REGION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%");
 
 // US specific default (used as a fallback if the geoSpecificDefaults request fails).
 pref("browser.search.defaultenginename.US",      "data:text/plain,browser.search.defaultenginename.US=Google");
 pref("browser.search.order.US.1",                "data:text/plain,browser.search.order.US.1=Google");
-pref("browser.search.order.US.2",                "data:text/plain,browser.search.order.US.2=Yahoo");
-pref("browser.search.order.US.3",                "data:text/plain,browser.search.order.US.3=Bing");
+pref("browser.search.order.US.2",                "data:text/plain,browser.search.order.US.2=Bing");
 
 // search bar results always open in a new tab
 pref("browser.search.openintab", false);
 
 // context menu searches open in the foreground
 pref("browser.search.context.loadInBackground", false);
 
 // comma seperated list of of engines to hide in the search panel.
@@ -1162,17 +1163,16 @@ pref("services.sync.prefs.sync.addons.ig
 // could weaken the pref locally, install an add-on from an untrusted
 // source, and this would propagate automatically to other,
 // uncompromised Sync-connected devices.
 pref("services.sync.prefs.sync.browser.ctrlTab.previews", true);
 pref("services.sync.prefs.sync.browser.download.useDownloadDir", true);
 pref("services.sync.prefs.sync.browser.formfill.enable", true);
 pref("services.sync.prefs.sync.browser.link.open_newwindow", true);
 pref("services.sync.prefs.sync.browser.newtabpage.enabled", true);
-pref("services.sync.prefs.sync.browser.newtabpage.enhanced", true);
 pref("services.sync.prefs.sync.browser.newtabpage.pinned", true);
 pref("services.sync.prefs.sync.browser.offline-apps.notify", true);
 pref("services.sync.prefs.sync.browser.safebrowsing.phishing.enabled", true);
 pref("services.sync.prefs.sync.browser.safebrowsing.malware.enabled", true);
 pref("services.sync.prefs.sync.browser.safebrowsing.downloads.enabled", true);
 pref("services.sync.prefs.sync.browser.safebrowsing.passwords.enabled", true);
 pref("services.sync.prefs.sync.browser.search.update", true);
 pref("services.sync.prefs.sync.browser.sessionstore.restore_on_demand", true);
@@ -1237,54 +1237,35 @@ pref("services.sync.prefs.sync.xpinstall
 // A preference that controls whether we should show the icon for a remote tab.
 // This pref has no UI but exists because some people may be concerned that
 // fetching these icons to show remote tabs may leak information about that
 // user's tabs and bookmarks. Note this pref is also synced.
 pref("services.sync.syncedTabs.showRemoteIcons", true);
 
 // Developer edition preferences
 #ifdef MOZ_DEV_EDITION
-sticky_pref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org");
+pref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org",
+     sticky);
 #else
-sticky_pref("lightweightThemes.selectedThemeID", "");
+pref("lightweightThemes.selectedThemeID", "", sticky);
 #endif
 
 // Whether the character encoding menu is under the main Firefox button. This
 // preference is a string so that localizers can alter it.
 pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");
 
 // Allow using tab-modal prompts when possible.
 pref("prompts.tab_modal.enabled", true);
 
 // Activates preloading of the new tab url.
 pref("browser.newtab.preload", true);
 
-// Remembers if the about:newtab intro has been shown
-// NOTE: This preference is unused but was not removed in case
-//       this information will be valuable in the future.
-pref("browser.newtabpage.introShown", false);
-
-// Toggles the content of 'about:newtab'. Shows the grid when enabled.
+// Indicates if about:newtab shows content (enabled) or just blank
 pref("browser.newtabpage.enabled", true);
 
-// Toggles the directory tiles content of 'about:newtab'.
-sticky_pref("browser.newtabpage.enhanced", true);
-
-// enables Activity Stream inspired layout
-pref("browser.newtabpage.compact", false);
-
-// enables showing basic placeholders for missing thumbnails
-pref("browser.newtabpage.thumbnailPlaceholder", false);
-
-// number of rows of newtab grid
-pref("browser.newtabpage.rows", 3);
-
-// number of columns of newtab grid
-pref("browser.newtabpage.columns", 5);
-
 // Activity Stream prefs that control to which page to redirect
 pref("browser.newtabpage.activity-stream.prerender", true);
 #ifndef RELEASE_OR_BETA
 #ifdef MOZILLA_OFFICIAL
 pref("browser.newtabpage.activity-stream.debug", false);
 #else
 pref("browser.newtabpage.activity-stream.debug", true);
 #endif
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -135,22 +135,33 @@ XPCOMUtils.defineLazyServiceGetters(this
 });
 
 if (AppConstants.MOZ_CRASHREPORTER) {
   XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
                                      "@mozilla.org/xre/app-info;1",
                                      "nsICrashReporter");
 }
 
-XPCOMUtils.defineLazyGetter(this, "gBrowser", function() {
-  // The TabBrowser class only exists in proper browser windows, whereas
-  // browser.js may be loaded in other windows where a non-tabbrowser
-  // browser might try to access the gBrowser property.
-  // eslint-disable-next-line no-undef
-  return (typeof TabBrowser == "function") ? new TabBrowser() : null;
+Object.defineProperty(this, "gBrowser", {
+  configurable: true,
+  enumerable: true,
+  get() {
+    delete window.gBrowser;
+
+    // The tabbed browser only exists in proper browser windows, but on Mac we
+    // load browser.js in other windows and might try to access gBrowser.
+    if (!window._gBrowser) {
+      return window.gBrowser = null;
+    }
+
+    window.gBrowser = window._gBrowser;
+    delete window._gBrowser;
+    gBrowser.init();
+    return gBrowser;
+  },
 });
 
 XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
   return Services.strings.createBundle("chrome://browser/locale/browser.properties");
 });
 XPCOMUtils.defineLazyGetter(this, "gNavigatorBundle", function() {
   // This is a stringbundle-like interface to gBrowserBundle, formerly a getter for
   // the "bundle_browser" element.
@@ -3242,16 +3253,18 @@ function goBackFromErrorPage() {
 /**
  * Return the default start page for the cases when the user's own homepage is
  * infected, so we can get them somewhere safe.
  */
 function getDefaultHomePage() {
   // Get the start page from the *default* pref branch, not the user's
   var prefs = Services.prefs.getDefaultBranch(null);
   var url = BROWSER_NEW_TAB_URL;
+  if (PrivateBrowsingUtils.isWindowPrivate(window))
+    return url;
   try {
     url = prefs.getComplexValue("browser.startup.homepage",
                                 Ci.nsIPrefLocalizedString).data;
     // If url is a pipe-delimited set of pages, just take the first one.
     if (url.includes("|"))
       url = url.split("|")[0];
   } catch (e) {
     Cu.reportError("Couldn't get homepage pref: " + e);
@@ -6705,23 +6718,17 @@ var CanvasPermissionPromptHelper = {
     }
 
     let uri = Services.io.newURI(aData);
     if (gBrowser.selectedBrowser !== browser) {
       // Must belong to some other window.
       return;
     }
 
-    let message = {};
-    let header = gNavigatorBundle.getFormattedString("canvas.siteprompt", ["<>"], 1);
-
-    header = header.split("<>");
-    message.start = header[0];
-    message.host = uri.asciiHost;
-    message.end = header[1];
+    let message = gNavigatorBundle.getFormattedString("canvas.siteprompt", ["<>"], 1);
 
     function setCanvasPermission(aURI, aPerm, aPersistent) {
       Services.perms.add(aURI, "canvas", aPerm,
                           aPersistent ? Ci.nsIPermissionManager.EXPIRE_NEVER
                                       : Ci.nsIPermissionManager.EXPIRE_SESSION);
     }
 
     let mainAction = {
@@ -6747,17 +6754,18 @@ var CanvasPermissionPromptHelper = {
       show: !PrivateBrowsingUtils.isWindowPrivate(window)
     };
     if (checkbox.show) {
       checkbox.checked = true;
       checkbox.label = gBrowserBundle.GetStringFromName("canvas.remember");
     }
 
     let options = {
-      checkbox
+      checkbox,
+      name: uri.asciiHost,
     };
     PopupNotifications.show(browser, aTopic, message, this._notificationIcon,
                             mainAction, secondaryActions, options);
   }
 };
 
 function CanCloseWindow() {
   // Avoid redundant calls to canClose from showing multiple
@@ -8261,17 +8269,17 @@ var gIdentityHandler = {
     let text = document.createElement("label");
     text.setAttribute("flex", "1");
     text.setAttribute("class", "identity-popup-permission-label text-link");
 
     let popupCount = gBrowser.selectedBrowser.blockedPopups.length;
     let messageBase = gNavigatorBundle.getString("popupShowBlockedPopupsIndicatorText");
     let message = PluralForm.get(popupCount, messageBase)
                                  .replace("#1", popupCount);
-    text.setAttribute("value", message);
+    text.textContent = message;
 
     text.addEventListener("click", () => {
       gPopupBlockerObserver.showAllBlockedPopups(gBrowser.selectedBrowser);
     });
 
     indicator.appendChild(icon);
     indicator.appendChild(text);
 
--- a/browser/base/content/moz.build
+++ b/browser/base/content/moz.build
@@ -8,19 +8,16 @@ with Files("**"):
     BUG_COMPONENT = ("Firefox", "General")
 
 with Files("defaultthemes/**"):
     BUG_COMPONENT = ("Firefox", "Theme")
 
 with Files("docs/**"):
     BUG_COMPONENT = ("Core", "Security")
 
-with Files("newtab/**"):
-    BUG_COMPONENT = ("Firefox", "New Tab Page")
-
 with Files("pageinfo/**"):
     BUG_COMPONENT = ("Firefox", "Page Info Window")
 
 with Files("test/about/**"):
     BUG_COMPONENT = ("Firefox", "General")
 
 with Files("test/alerts/**"):
     BUG_COMPONENT = ("Toolkit", "Notifications and Alerts")
@@ -32,19 +29,16 @@ with Files("test/chrome/**"):
     BUG_COMPONENT = ("Firefox", "General")
 
 with Files("test/contextMenu/**"):
     BUG_COMPONENT = ("Firefox", "Menus")
 
 with Files("test/forms/**"):
     BUG_COMPONENT = ("Core", "Layout: Form Controls")
 
-with Files("test/newtab/**"):
-    BUG_COMPONENT = ("Firefox", "New Tab Page")
-
 with Files("test/pageinfo/**"):
     BUG_COMPONENT = ("Firefox", "Page Info Window")
 
 with Files("test/performance/**"):
     BUG_COMPONENT = ("Firefox", "General")
 
 with Files("test/performance/browser_appmenu_reflows.js"):
     BUG_COMPONENT = ("Firefox", "Menus")
deleted file mode 100644
--- a/browser/base/content/newtab/alternativeDefaultSites.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
-  "directory": [
-    {
-      "bgColor": "#ffffff",
-      "directoryId": 10000000,
-      "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAIX0lEQVR4nO1afXDbZh1+sxbWsbGvsrLbuBt36766sR3sOEgiuU4kx2vTpFGKm0SKsyyOlI8laUZTulLojQEHx4CyAaNnt72yrivklo1YSpxcW7YVbKXHgCvduCvroDt6o6OtLSWN1MRWX/5I4imyJMu2bPNHnrvfSZbf6P09z+/jfV+3ACxhCUsoAEouNWGlMRLri5GuZwUSe1Ug8bcFEjsjUPgHAoX/UyCxkyKJjQoU/iOhCd8WJSvW/8vpXFFsx7PGeaJsVaytul+g8KMiic+IFA7NTNB/rggk/jeRcu26RGFris3JEqIUtkFsdo2KFK6kI52pCSR2UmirZgY9YFmxeaYg1uyqFSj8lMXI5mofRb3rOwEAJcXmDS72ex8QvO43skjv3MeT2DtRX2150cgLzVUDIonF8xBh64KQ2FWRwncPejyFK4tYq/Nmoa1mPE/pnZ1ILe4TFxpdd+SdvOhxrhabXaeLTVjfsHfzSj5K4V8QKfyjnGs3P2UiCt/v/1LeyAsNlXebkbeRSOZ/Q+JCrBH/Yt7IX+qlbhS96dM+Y+dJLC6S+BWRwmazFizf5AEAQPRtHLEhukqMwo8KTfg2oamy8t+e0uvUczwDwDWxhopHBBLvElrc+wUSm/r/IN9a3ZtrbYqUe9eHTc7PZDLvoAcsi/lq2wQSO1M88k93r7ayjzdI76sxEv/5hdryT+foRknM696q9qMg5AEAQHx83WhWtU5i56PtG1E7fYkO+B4SKNd7AoWLBSEv9G3Asol8zOs+ddFTeWc+fDrXgq2MNmEP5+PdKZB/XR4RvRnWe8tjJ8+1ECsL4mA+EQ+vcCg8gHHuPjjZvc5S6guU6/3/POG5rdi+24IEv+KwEgFQ4QFU/rAKTu90pal5fCY60PlQsf22BefHwfUKD2YVfl6ACIAKfx2UX0QNBYj6arqL7bdtSIQBnYy+2iIAzg49Cid9bm3qv11sn21FggeHUwSILGQCgIljd8Kpreq+4Koqts+2QuGBmBL9FLsFSj+sgAKFnyq2v7ZCDoO7dKOvvc7fS3vcW4rts61I8OBxXdI6/UCJADgVvmGVHfMSAelgfUA6VBeQDqmv2nuzZ3rf6Y2r3SM7DB1RwmCnOsLaiGuenbWD/JwAcqI+IEPCL8H6gAwX7omADIn5z/Wqe0Iz1sgI3edSv6EjcR78OEk4jQiJCNhnlwD1ATlBmDqdCUHzcYRf3mXoSCIMXjdK95SeEAbfslUAk4iaEc1EsLnx0vNmAhw3q3mNAFvtFCBd2i8i4bdWAgYCDBkLwIMJw8antTDos12ARSTNM8JK5Amd8URAPmosQAS8Zdr41N/lIQOS0Z2/pkZe0iWoS35+rIY8rPfLvzcWgAdDljMgAr5tlwCEWgArjUxnnJXSmX8eMnQkPrH8OasCJMJgfyEE0KZxMrJ+i2WgyZq6gHTQ0BGFv+abujs//ab4gV0CqEvAar1n0gQXizj9PUNHEmHgTSFt1At4O3eCH+8D0tW2YUmoMkKvfyQzwC/vMHREegN8Tpe4zjIY55fD14+X9tgiwC8mV2ZrHS/LGOGXRd3y8aeKVee/3GrqjBIGMcMsmL/GJu6AW4+1QZRl/mKHADmipD4gz1jJHCIgw9oXJ+8zfVsi/ImXU7bDquvfI2ugZ7wHoiwDUY6BTrbTWRie+ti0d7rGrHTU5UD45StpX5iILPMZrQTD4Q0QG+2GKMckzcF28AXgaYiv7ZNesdokCb90PO0LP2TBpxQezKpFkPmb4Q/ebFlEHOWYZBY8FtriKwDXFDAHhLvr/bJi9TzQtPeycQNUI3HihkML5M9NfB4+caRTl/jHRsvtb333gTzzTUHDPonNZFkkfjVl7Zfr+MRtiMID+McICqtDvfrE2cWfHRxz2j321K155pxE84HLLWb7BK0odX75TEYTBI43hB1ch0HE554h7GJhKrkn/4wPMjfliXMSO4alcsIvx/UanZE17pcGMppkU2iL2zDt9QSZtwqu66/Okdbb88Qd7PydVFYfkGVthLWHHk1JyOteuHRjxpNh3JNjRtE3EgDlGIiwzLlqrq/MbvKtLwkewi/PalPc8PyQPDdIP8lqQvdw92qEZWbNyBqJgnD0VTTI7H74Je/1uRL/8mDr7VWjfYeJkecgdfC/6c8JavPL0+6fitn3JtdIzxbdqLPqiNMmwtAxR7BzZ+mgL2MnHGzHPQhL/wzlmCsLc64PbYPU4Xd1zwN6WdCwT/p61uQXsH6sL5TS/dOUgY4QCZRlxsuD9EDZsM/x4KDnk5ppSsqGfHehw3QjytHfQVj6HaP+U8F1wZbhMf1Dkerzpr3Sn4Ad/5/Yc2T7TQ6OOW2YBWZimAsVRzlaRoL0DMLRV/WW19SVh05+v5nbAxsPCPpZ4Jclwj95b87kF+BgO+5Bg8yFFHKZZkO68XqimoyvGd0FqUNnU/pA1yvTdbaRXwDCtj2CsszFjFLfSjZoRbEiqEqoqtE+6H2VT5LfvPfydtvJJ0V4jb537QhzxjLRdMSsimIhq5q538DNgSnbfqs0FoHrusUd6j2ScdTNyGZTNovfHa8Z6/fmnbwaTq5r+1wj0ziZrjlmvIKYP3ew9Hvk+NOPFpT8AjxHd6ypGOl607Z+YDUL5s4iChpkdq8b7b22KOTVQIPtGxet3bmQtVA6eKhnyBP6hvnPW8UAwvpq1nIdoeS6bpWY0fK3aMfJTCMc/csqtuf+YvNMi68Mt38WDTJPoSx9DGHpmaxLI8hcqBzpCiDB9ibnM87lxeaVLUrKg+1fRVimby3LPItw9G9Rlj6Bssw/EI4+i3DM+0iQPomy9JiD69hdztI7SoPtTWWvddry7w5LWIIx/gdCuvcjoZqlLQAAAABJRU5ErkJggg==",
-      "type": "affiliate",
-      "title": "Google",
-      "url": "https://www.google.com/"
-    },
-    {
-      "bgColor": "#E62117",
-      "directoryId": 10000001,
-      "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACd0lEQVR4nO3av0tVYRzH8WOIBEVDUUIGCa32FwQ5OrS42NKeRUOTdGmoqUGiLVBqa5UG+7WUREGiEqhTDkVJEA2iYZBkxKvhHumo96o3uM9z0ucNZ7zn834+XO59znm+WZZIJBKJRCKRSGwCx3AWfbiIaxjEPYzgOd7gLWbwIb8WsFjjWrU9q3U+u1C4/0yeOZ47jOROg6jkrn25e3uji27NbzC9A9n/hWnVNbVut/hOTMZ1bSqT6Ky3+A58jOsXhE/o2Lj4FryILBaSF2gpFtAT2ygCPcUCHse2icDTtcW3YSW2TQRW0JahK7ZJRLoy9Ma2iEhvhoHYFhEZyDAU2yIiwxkeBgj6FSDjXxjN8CpA0A1cxucAWY0wkeFdgKBK/pe7H1fxNUDmTpjLMB8gqLJh631A9dF6IUD2Vsxn+BYgaF0BhSIO4WYgh1osZVgOEFSzgEIRh3EL3wO4FFnOAgVtWUChiKO4gx+BvJSqgEIRx3EXP5stVsoCCkWcxH1N3EeUuoBCEafwshlipS8AJzTxW1DaAnAEtzX5B7F0BeAgrmMphFhpClB9M3UFXwI5oQQFYB8u4H0gl3VE3QninOoxVyyWozwL4AxeB8jdjqWgT4M4jUcB8nbKfKj3AUN4gN8BshphLtQbobIyEeqdYFkZzTAc2yIiw+lcQDoZSmeDe/t0ON+gPIltE4Fnxa3pnp8QacFYbKOAjCnOCOUldKhOUO12Nk+JFUroxFRkwWYypd6cYKGEVvTbfZOil2w3KVqjjHZ047xqKRWbZ4XHVed2Z/2d5a0167vYgHC9z6/df9bWs8L9uXO3RmeFE4lEIpFIJPYKfwAcall+TY3q/wAAAABJRU5ErkJggg==",
-      "type": "affiliate",
-      "title": "YouTube",
-      "url": "https://www.youtube.com/"
-    },
-    {
-      "directoryId": 10000002,
-      "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACT0lEQVR4nO3bzWsTQRgG8PlPHMVLqRVMoQiFehJyUBAFtRCFHspExaaSoFg8CMGPSg+R3kQhh3osIbOlMVrbGKtrsbYESTbB0gqNVGu1WCkWutnXg+ihQjqxi7Oz8w481533+V32iyGEEEIZ76Rho0SZ4ewOG+D3UMatXSx9nPwqb5ySPZC0dPMzhDJelD6IrDCjQijjtvRBJIWGeY3IHkJ2EED2ALKDALIHkB2lAJoujkIwnoNQwoQL96aha3AKQgkTTtyZhKM383D4+gQEoll/AQRiWbg1XILZ+VWwaw6IrE3bgZbejNoAe8+PwEC6DOsbm0Klt679lxQGCESzMD335Z+KKw+wrzcDpcVvOyqvNMCwubjj8soCnBx44Up5ZQGeFZf1BWi7/BhqjthtzpcAseRsQwVrjgNzS9/hZWUFJq3Pf6U5MqoWQHJ8Qbh8aqoKB688cWVfzwBMvP0kVN6srMCec+7t6xmAmfmvQgCRBzOu7usZgHJ1TQjgyI283gCHrj3VG6C9bwwBEAABEEAtgAPRR9A3VKibpdUfQgD9KWvba529+8pbAMF4TqicW+th/r3eAP0pS2+Anvtv9AY4dvu53gCtMfGfI74DWN+wG5rNdwDl6preAGOFj3oDJMcXvAfQHMlAKGHWTeWD2KPw1aFC3et0NPi9wDPvAq/fif0LDMZzru6LALKLIwACIAACIAACIAACIAACIAACIAACIAACIMD/BvDKwUkZAJRx2zNHZyUBFAntTp+WXV4iQCf5c3yecUsXAMq49bv8Txsl6ZCTabOAAAAAAElFTkSuQmCC",
-      "title": "Facebook",
-      "type": "affiliate",
-      "url": "https://www.facebook.com/"
-    },
-    {
-      "bgColor": "#ffffff",
-      "directoryId": 10000003,
-      "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA/CAYAAABQHc7KAAAEyUlEQVRoge2abYhVRRjHf7veVqSFhIQwa7E3ojXNpSiNgl0S+tAHKUjohbQohUgqKKwMSXpbsATdqOgFU4zKpAzMioploxI/WFBZmhRlL/S2lbpsudvd24dzjve5c58558ycey9B84MB95x5/vM/d+bMzDNHCAQCgUAgEAgE/rf0AOd6lJmKVrdDfI8SfxawIKNcEscfa8TOzBFrlj6Aimd5XnmAbx01TD5xiL3IiH3Y8zm4DXgaGALGMip/DDwHDACXKQ9wA/AiMJyi8T3wAnCvEr841t9tiR2JY/uB443YC4BHgA3ApyntTxD90FuAlaaBU4EfLIHvKIZtnAT8ZtE5O6fGCiNuFJiTM7YNWKe0PQScmRV8ncX4+zkbT1hq0bkyZ/wyI+5ux/bPM+I/ACbnCSyhv8tloMvBQAnYr+h8mDP+PRHzGXCMQ9sA14j4ceAMl+A70HtvjaMJ22jqy4i70Kh/sWO7AO+K+Jdcg6cCh6k3/gfQ6aBTAr5UdN7OiHtL1H3NxXhMN9Fkl2jM89BgPXrv3eKoc71Fx2ZqvqhTJv+kKRkQGjs94gE4PTZgGt9DNMvmpQR8pehst9R/Q9TZ5OG7EzgkNK720DjKNvTeu9RRZ4miMUH9bnCeuH8EOMXD881C40egw0PjKL3oP8Cbjjq2FWGrUW+HuDfg6XmP0NA2W060GYKy97odtbQVoQzMiu+fL66PACd4+O0VGqPANA+NOm5CHwVPOeqUgH2Kzub4/uvi2gOeXrcU8GdlCtG7ZBr/C5juqHWtojMOXCX+HgaO8/B5YqyV6GjZpjf3oI+C+x11JgF7FZ1/xL/v9PS4WmgMempYsW2MfsdtYwTRsqT9mBXgANGIc6WD2lG60EMjk0fRTS931GkHPrdo3ejpbZHQ2B+30XC6iNZm0/Q3RBOcC7Yc4WRPb0NC43ZPjVxsRDe+yFHHHLJJWevhabaIP0z0ujaNWdQmGUn5yEPrPkVnBPe1+0kRv97DhzPb0UdBr6OObZv9kIOGnJzLRPlL0+lFN+6yPe5BH0kV4E/yD+PlIm6bQ/uF2Um98Qlgbs74V5V4WVbl0GgDvsB/BBbiCnTj2lG5yVyqvX+QaOSYOsNk7y8WiPo+c1Ah2tFPesbJTmFfEfX7qU2BZVmRoSPnkMU+D1EUW5L0WErMHKq9P0o149NeqZ+w7wq7qO77f02p11Qmo6/laWnoVlFvnbh+uaJTAW616Dwo6rjmIw3lLnTjminZ+38DM8Q92yv1HfUnOh3AL/H9I7hnpA1lKrXnb0nRkqSXxf0nFC3bK7XMqCdT6o2NeIiirEE3Lvfks6kesI6hf1m2nTt8TW2uIeeLhub8vsxAT5IOUB2+8qTm2RStlYqOnOV7xLXBRj5EUWxJ0hKic/2k98dJ367azh32Es0Tz4hrTcn5fZE9I8s+ajc6m20CgrUWrdVEK0yFJub8RRhEN56UMjk+TVO7xtuK6yFMS1hIuuk82+SETSk6h3A/hmsJ7egfPypEh555ej/hHOzZYktyfl9keiqLzzc+LUlqWc7vSyfRJ3Rpegw4zUOrj/ofoKU5vy/91Jp+vIDWLkPL/J9h/0mmAT9TXa58vvIkzKe6ydpQ3FogEAgEAoFAIBCI+Rf5q90lTPZHIwAAAABJRU5ErkJggg==",
-      "title": "Wikipedia",
-      "type": "affiliate",
-      "url": "https://www.wikipedia.org/"
-    },
-    {
-      "bgColor": "#400090",
-      "directoryId": 10000004,
-      "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAD3ElEQVR4nO3bS4xecxjH8WmLBVVEx63JBIkEISkhJqURpAsZQioWqpeNSxraYlKpSwiDIRY0aSakqgS9qHRBIhKxYdFFFxWXIGkilYZEUCKj4zLzsfi/LN55zpiZc/lr+/6Ss3nfc57ze77n9r88/y7swxaswgLM7jpMhTlYiNWtnPd1Ga9RfIVtuB+L0J3b/FSFeejDQ9iBvRhrTzYCUKTv8RFewlrcgAtxQsYk5+Ii3IQHsBm78ONkk5oKgIn0Mz7BO3gBA7gHS3EtLsXZre1UnITj2pI5vvV7D85BL67DCvRjEJvwHj7HcBXGqwJwyKoDILeB3OoAyG0gt8oAGMYj0qdnJ17DY3i2vK1CPYmn8Cq2YwgP4rfpBix7BwwE3+aZ2F0ybqQPMSM439NlgpYFMILzAlO9glZXCf2F+cF5LsafZQJX8Q4oujKbK4j9j4aC+EdhT9nAVb0Ebw8MduNABbF/wMlB/LUVxK4MwE84JTC5uoLYK4O48/BrBbEr/Qy+XnCbfloi5h7MCuJurcSxagGMYWFg9qr/SbxQVTeEiq7Ym9OI9UYQ52ipJ1iZ6mgJ3h0Y7zG17usvOC2I01+12ToAHBCMIGHdFGKsCo4/QwJTqerqC2wMEjgGX0zi2KLH6JU6jNYFYBSXBElc/R/HjaE3OO4y1bYs/1WdvcFd4hbilgmOie6cGa1Ytaju7vDSIKHTxc9yUYtvWZ0G6wawH8cGSa0J9r0t2G92K0ZtamJA5PEgsfaOTNHjMlC3uSYADKMnSG6B9GIr6uqehYN1m2tqSGxre4KtJDdhfcF/O5ow1hSAMVweJNmNOcHvlbb3J1KTg6K7MTO62m3Jz1LBQMdk1fSo8IpJALizSUNNA/jWBNPvOFGahG1MOeYFnpgAwHNNm8kB4CDODJI/F380bSbXzNAzAYD1OYzkAjAYABjKYaQDIMdJxQDqnFMsVC4A6wIAgzmMdADkOKkYwKM5jOQCcFcAYCqjxpUpF4Bovu+IB3BfDiO5AIzrFWJlDiO5ACzpABgP4I4cRnIBWBwAWJLDSC4AfR0A4wHcksNILgCLAgB9OYzkAnDFkQ5gDZbj3ta2XCp5bVydYuncBnKrAyC3gdzqAMhtILfqBDCCb6SZ3velatGXsUFa5NC+vdjatrf2/QAfSyUyv9dlsgyAEXyGt/G8VBl+PS7A3PaGTllJCy7n40Zp8GQD3sWXSgCaDIBRqcBxGx7GYmll57hixlySaojPx83SuqW3pLXC0wKwX7oF+3GloILjUJE03X6NtAh8J76LAOzFRtwqKGY63CStX14mLen5+m9Vgqdbrd+9cgAAAABJRU5ErkJggg==",
-      "title": "Yahoo!",
-      "type": "affiliate",
-      "url": "https://www.yahoo.com/"
-    },
-    {
-      "directoryId": 10000005,
-      "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAJdklEQVR4nO1ba1QTZwL9iCY8hCDxDUpYOIUDBOVZAlJ5NQXRFlEQ8YGiRaqESlhxeRQ3FAWURRC6FYglqBHTEaI8Eg+CRMRatfKwLNL6oqer1h57XEWYbwJK9sdKixiSmRCCbrnn3D8w351770wy3zd8ADCJSUxiPMHhcPS3bdv2/tq1a9MWL16MODs7t5iamt4zMjLq0dfX76VSqU8sLCzueHt7S+3t7QtjYmLWJyYmzp1o32NGSUmJd0BAQLmRkVEPAEBOhCQS6bm3t7c0MjIyHACgMyEB1AGCILTY2NgUOzu7fwGCoUfj/Pnz/x0XF/fXgoICXW3nIYTs7Owlpqam94CGgo+ktbX1j4mJiY7azIQbMTExu3V0dF6AcQo/RF1dXYggSIj2kuFAfHx8Lhjn4ODVElCxWOygpXjKkZWVxQZaDD9EOp3eXV9fb6yVkKOho6Njgb6+fp8ig9pgfHx8gjZyjgYdX1/fhtHMqSKJRHpOJpNl6o4HAMidnJxatJJUEWpraz3xmBxOExOT30JDQ/+elpZmD14+26uqqubExcVFzJs3T53H5uCJEydMtZN4BKKiovKJmA0KChLu3bt3zmh6Bw4c0F+3bl0BEU0AgLygoCByXAKqgq2tbSdek0FBQTV4dZlM5kW8ugAAOZPJ/IeGIuHH9evXp+no6DzHa7K+vt4Lr3ZiYuIOvLoAALmnp6dQQ7HwIzc31xqvQRsbmy5AYC6fnJzsjlcbACD38/M7p5lUBBEeHp5lbm7+E4lEUnonREdHpxPRLSwsNFWmN5Kurq5XNZNITfj4+EwtLCw0dXFxcebz+UFhYWFbmExm6qZNm/IjIiKyampqDIjonTp1ajp4mwrQNP70BfD5/D9PAcXFxQZcLteOwWCw9u/f/3FwcHC6paVlOfg/K4CUlpbmEB0dvSEkJCTLxsamwtnZuXXmzJmPAACDgEBYRXxjC8jJyfFYtmzZYWNj48dgjCGV8Y0qICsryyQiIiKVTqf/BMYxNHgTC8jPz/+ISqU+AVoKDt6kAnbs2MGeMmXKANByePAmFBAbG5utyJi2OKEFJCcnx+MxqYizZs361d/fvyw9PX0bg8FgZWRk2FZVVc1pampaQERnwgoQi8VLVK0DRpJMJstWrlx5hMPhvMflckmKdN+amSDRdbuenl5fRkaGnyrdt6KAsrKyD4iYpFKpTy9cuPAuHu23ogAmk9lIxGRCQsLneLVLS0tnEdHWegFisXgu0b8ANTc3W+LVT0pKsiSirfUCDh06tJyIQSsrq5tE9PPy8jyI6Gu9gMDAQA5Bg9VE9Hfu3BlFRJ/BYHSMPRUBsNnsfUQMksnkciL6q1ev5hHRNzQ07AHa3D9A9N19QEAA7lfiAAAdOp3eTUQfACBHEMR87MlwgmgBZmZm9wHOK1RUVLSFiPYQd+/eHaOheKrB4XCyiBrk8XguqnTb29vNDAwMeolqAwDkCxcuvKbBiMoREhLyKVGDy5cvr1Cm2d3dPd3Ly+sCUd3h3LNnT7xGg46GoqKiQHUMbt68uZjL5VJG6qWkpPjS6fS76miO4Ivm5maVd9qYUV5ePlPdtb+FhUV3cHBwkbm5efrGjRvz7O3tr2og+O90dHRslUqlUxX5lkq5U7HmJEtUsnTxwG0kEJ7b4Cer32ArlXIVHq8ULBarVpPGNcng4GDP4V6xloxArNq3oq+M9hTlUeSvsfwvPxMuoKGhwWO8N0RRKBSM6Bg6nf4jgiC0zk6Egl3czsYQhxsKQ48g4QIAAMDf3//0eIWn0WiPjh075jx79uyHeMfY2dl1IAgyFwAAZA1rjqE8ihw9rPscrXRp7xO5lckaN6X0t+dt7m/LiYanPI+iPPLgmApoa2t75+W7fY2GX7RoUcvx48fpAAAgEom88NwJLBbr65ycnGlD3gZuli15VhfC6JZy9Ubzj1W6to6pAAAAEAgEDsbGxv/RVHh3d/ezEomEOvwcqamp6crGsNns/NHeLg0HPPOhV98Pf2ynQRHG+ZcFDKpdAAAAFBcX+6qzF3gkly5dqjCIVCrVs7e3v6RozKpVqw6q8idrybCFonfrUB5FDqsWfzv0c1jh2IHyKHIotL0J+lsyY7CqJXmyO4hamw/Ly8vnhIeH51Op1KdEQtNotN9WrFjxpVAodFOmv337dkMmk1k9NI5CoWCZmZk7EQSZouj4bilfT/ZtUjhW4yNCDxv0ozyKHJaZ9Mq+S1sDAACdnQgF8o1RlEeRy5picsDA3dPv9QnMHqI88iAUudYNdJV4q1NEXFyc7q5duzZ4eXmdtLKyukUikV6ZL1Cp1CeOjo6tHh4eRVwudwWfzx/1MzoSXC53alRUVCaLxapjs9kBio55fC3bGPvm0wRUQL/3yjc9n9Yz0HX090zolTSP//2OPIjdEVkDAAB42nmYJjsbWjo0CEMcfoCNkXvR5lh3BAlT2LQqhIWFTZFIJFSJRELdunUrWR0NVXhc/zdj9MxHa6B4qRAemfHasx6rYUnQjn8uGD5G9k3CHpRHkcvqQk+8Joh1lX2AHl9wf+RkAWtYvx9eSvaWSn2Iz5w0jId1O6fJLn8Wila6iVCe/oCiZ3sff8YT7CLnE6BgJQoRhxtoqcmz3l8vK9629+xW6Sx4dnUmLJv55DXxo3MeQ8ThDKxlfS77Pm8F1pxkqegkmsItSZxu75nAhf1NMZFY47ov4MlFzejLz69ClhrB/vObc3uuZM5QpIf9fM4K5VHk/W25sSpP3tdaaArPrBSgJbovlM6m+LQeWO13HqtwO4i1Zn0CRZ5+2Hf7bB5cK8a9P6hbytfDOgqsMJErC7vyWRw87VUERR5X0VJDiGc2h/IocljL+rr3Klfpv9pg9xttsLOrVIcfDtltEQOtcP0CFZg/wGvmjysyvQ8VmP8ChTa3McThBiZya8NEbm3YSUYXFNrcRgXmv8Ay2jOUp0tMd9gdidWHFsiuH2QQCqUOuFwuSXY5ZT1a6dyullkNEiKMLky6NaYTeX2JrRXILqcslIkDk2GFYyP6lSE27oGPzHiKVTiJZdV+qf2dh50mJPRo6Jby9bBLycvRSpcCeNLpe7SEovw7Aw+/MpDBUx5XsNqAbHgp2buzc4KutDp4dHGXEVq3xh02fbwFq2Htg5WuQljlcwFWLOqAJ97p7hOYPewTmD2EQuu76Emn67DauxmtdEawap8ceH5TNFofznxQs5XQBstJTGISk1AX/wUPVWOeSpK50AAAAABJRU5ErkJggg==",
-      "title": "Amazon",
-      "type": "affiliate",
-      "url": "https://www.amazon.com/"
-    }
-  ]
-}
deleted file mode 100644
--- a/browser/base/content/newtab/cells.js
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifdef 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/. */
-#endif
-
-/**
- * This class manages a cell's DOM node (not the actually cell content, a site).
- * It's mostly read-only, i.e. all manipulation of both position and content
- * aren't handled here.
- */
-function Cell(aGrid, aNode) {
-  this._grid = aGrid;
-  this._node = aNode;
-  this._node._newtabCell = this;
-
-  // Register drag-and-drop event handlers.
-  ["dragenter", "dragover", "dragexit", "drop"].forEach(function (aType) {
-    this._node.addEventListener(aType, this);
-  }, this);
-}
-
-Cell.prototype = {
-  /**
-   * The grid.
-   */
-  _grid: null,
-
-  /**
-   * The cell's DOM node.
-   */
-  get node() { return this._node; },
-
-  /**
-   * The cell's offset in the grid.
-   */
-  get index() {
-    let index = this._grid.cells.indexOf(this);
-
-    // Cache this value, overwrite the getter.
-    Object.defineProperty(this, "index", {value: index, enumerable: true});
-
-    return index;
-  },
-
-  /**
-   * The previous cell in the grid.
-   */
-  get previousSibling() {
-    let prev = this.node.previousElementSibling;
-    prev = prev && prev._newtabCell;
-
-    // Cache this value, overwrite the getter.
-    Object.defineProperty(this, "previousSibling", {value: prev, enumerable: true});
-
-    return prev;
-  },
-
-  /**
-   * The next cell in the grid.
-   */
-  get nextSibling() {
-    let next = this.node.nextElementSibling;
-    next = next && next._newtabCell;
-
-    // Cache this value, overwrite the getter.
-    Object.defineProperty(this, "nextSibling", {value: next, enumerable: true});
-
-    return next;
-  },
-
-  /**
-   * The site contained in the cell, if any.
-   */
-  get site() {
-    let firstChild = this.node.firstElementChild;
-    return firstChild && firstChild._newtabSite;
-  },
-
-  /**
-   * Checks whether the cell contains a pinned site.
-   * @return Whether the cell contains a pinned site.
-   */
-  containsPinnedSite: function Cell_containsPinnedSite() {
-    let site = this.site;
-    return site && site.isPinned();
-  },
-
-  /**
-   * Checks whether the cell contains a site (is empty).
-   * @return Whether the cell is empty.
-   */
-  isEmpty: function Cell_isEmpty() {
-    return !this.site;
-  },
-
-  /**
-   * Handles all cell events.
-   */
-  handleEvent: function Cell_handleEvent(aEvent) {
-    // We're not responding to external drag/drop events
-    // when our parent window is in private browsing mode.
-    if (inPrivateBrowsingMode() && !gDrag.draggedSite)
-      return;
-
-    if (aEvent.type != "dragexit" && !gDrag.isValid(aEvent))
-      return;
-
-    switch (aEvent.type) {
-      case "dragenter":
-        aEvent.preventDefault();
-        gDrop.enter(this, aEvent);
-        break;
-      case "dragover":
-        aEvent.preventDefault();
-        break;
-      case "dragexit":
-        gDrop.exit(this, aEvent);
-        break;
-      case "drop":
-        aEvent.preventDefault();
-        gDrop.drop(this, aEvent);
-        break;
-    }
-  }
-};
deleted file mode 100644
--- a/browser/base/content/newtab/customize.js
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifdef 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/. */
-#endif
-
-var gCustomize = {
-  _nodeIDSuffixes: [
-    "blank",
-    "button",
-    "classic",
-    "enhanced",
-    "panel",
-    "overlay",
-    "learn"
-  ],
-
-  _nodes: {},
-
-  init: function() {
-    for (let idSuffix of this._nodeIDSuffixes) {
-      this._nodes[idSuffix] = document.getElementById("newtab-customize-" + idSuffix);
-    }
-
-    this._nodes.button.addEventListener("click", e => this.showPanel(e));
-    this._nodes.blank.addEventListener("click", this);
-    this._nodes.classic.addEventListener("click", this);
-    this._nodes.enhanced.addEventListener("click", this);
-    this._nodes.learn.addEventListener("click", this);
-
-    this.updateSelected();
-  },
-
-  hidePanel: function() {
-    this._nodes.overlay.addEventListener("transitionend", function() {
-      gCustomize._nodes.overlay.style.display = "none";
-    }, {once: true});
-    this._nodes.overlay.style.opacity = 0;
-    this._nodes.button.removeAttribute("active");
-    this._nodes.panel.removeAttribute("open");
-    document.removeEventListener("click", this);
-    document.removeEventListener("keydown", this);
-  },
-
-  showPanel: function(event) {
-    if (this._nodes.panel.getAttribute("open") == "true") {
-      return;
-    }
-
-    let {panel, button, overlay} = this._nodes;
-    overlay.style.display = "block";
-    panel.setAttribute("open", "true");
-    button.setAttribute("active", "true");
-    setTimeout(() => {
-      // Wait for display update to take place, then animate.
-      overlay.style.opacity = 0.8;
-    }, 0);
-
-    document.addEventListener("click", this);
-    document.addEventListener("keydown", this);
-
-    // Stop the event propogation to prevent panel from immediately closing
-    // via the document click event that we just added.
-    event.stopPropagation();
-  },
-
-  handleEvent: function(event) {
-    switch (event.type) {
-      case "click":
-        this.onClick(event);
-        break;
-      case "keydown":
-        this.onKeyDown(event);
-        break;
-    }
-  },
-
-  onClick: function(event) {
-    if (event.currentTarget == document) {
-      if (!this._nodes.panel.contains(event.target)) {
-        this.hidePanel();
-      }
-    }
-    switch (event.currentTarget.id) {
-      case "newtab-customize-blank":
-        sendAsyncMessage("NewTab:Customize", {enabled: false, enhanced: false});
-        break;
-      case "newtab-customize-classic":
-        if (this._nodes.enhanced.getAttribute("selected")){
-          sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: true});
-        } else {
-          sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: false});
-        }
-        break;
-      case "newtab-customize-enhanced":
-        sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: !gAllPages.enhanced});
-        break;
-      case "newtab-customize-learn":
-        this.showLearn();
-        break;
-    }
-  },
-
-  onKeyDown: function(event) {
-    if (event.keyCode == event.DOM_VK_ESCAPE) {
-      this.hidePanel();
-    }
-  },
-
-  showLearn: function() {
-    window.open(TILES_INTRO_LINK, 'new_window');
-    this.hidePanel();
-  },
-
-  updateSelected: function() {
-    let {enabled, enhanced} = gAllPages;
-    let selected = enabled ? enhanced ? "enhanced" : "classic" : "blank";
-    ["enhanced", "classic", "blank"].forEach(id => {
-      let node = this._nodes[id];
-      if (id == selected) {
-        node.setAttribute("selected", true);
-      }
-      else {
-        node.removeAttribute("selected");
-      }
-    });
-    if (selected == "enhanced") {
-      // If enhanced is selected, so is classic (since enhanced is a subitem of classic)
-      this._nodes.classic.setAttribute("selected", true);
-    }
-  },
-};
deleted file mode 100644
--- a/browser/base/content/newtab/drag.js
+++ /dev/null
@@ -1,151 +0,0 @@
-#ifdef 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/. */
-#endif
-
-/**
- * This singleton implements site dragging functionality.
- */
-var gDrag = {
-  /**
-   * The site offset to the drag start point.
-   */
-  _offsetX: null,
-  _offsetY: null,
-
-  /**
-   * The site that is dragged.
-   */
-  _draggedSite: null,
-  get draggedSite() { return this._draggedSite; },
-
-  /**
-   * The cell width/height at the point the drag started.
-   */
-  _cellWidth: null,
-  _cellHeight: null,
-  get cellWidth() { return this._cellWidth; },
-  get cellHeight() { return this._cellHeight; },
-
-  /**
-   * Start a new drag operation.
-   * @param aSite The site that's being dragged.
-   * @param aEvent The 'dragstart' event.
-   */
-  start: function Drag_start(aSite, aEvent) {
-    this._draggedSite = aSite;
-
-    // Mark nodes as being dragged.
-    let selector = ".newtab-site, .newtab-control, .newtab-thumbnail";
-    let parentCell = aSite.node.parentNode;
-    let nodes = parentCell.querySelectorAll(selector);
-    for (let i = 0; i < nodes.length; i++)
-      nodes[i].setAttribute("dragged", "true");
-
-    parentCell.setAttribute("dragged", "true");
-
-    this._setDragData(aSite, aEvent);
-
-    // Store the cursor offset.
-    let node = aSite.node;
-    let rect = node.getBoundingClientRect();
-    this._offsetX = aEvent.clientX - rect.left;
-    this._offsetY = aEvent.clientY - rect.top;
-
-    // Store the cell dimensions.
-    let cellNode = aSite.cell.node;
-    this._cellWidth = cellNode.offsetWidth;
-    this._cellHeight = cellNode.offsetHeight;
-
-    gTransformation.freezeSitePosition(aSite);
-  },
-
-  /**
-   * Handles the 'drag' event.
-   * @param aSite The site that's being dragged.
-   * @param aEvent The 'drag' event.
-   */
-  drag: function Drag_drag(aSite, aEvent) {
-    // Get the viewport size.
-    let {clientWidth, clientHeight} = document.documentElement;
-
-    // We'll want a padding of 5px.
-    let border = 5;
-
-    // Enforce minimum constraints to keep the drag image inside the window.
-    let left = Math.max(scrollX + aEvent.clientX - this._offsetX, border);
-    let top = Math.max(scrollY + aEvent.clientY - this._offsetY, border);
-
-    // Enforce maximum constraints to keep the drag image inside the window.
-    left = Math.min(left, scrollX + clientWidth - this.cellWidth - border);
-    top = Math.min(top, scrollY + clientHeight - this.cellHeight - border);
-
-    // Update the drag image's position.
-    gTransformation.setSitePosition(aSite, {left: left, top: top});
-  },
-
-  /**
-   * Ends the current drag operation.
-   * @param aSite The site that's being dragged.
-   * @param aEvent The 'dragend' event.
-   */
-  end: function Drag_end(aSite, aEvent) {
-    let nodes = gGrid.node.querySelectorAll("[dragged]")
-    for (let i = 0; i < nodes.length; i++)
-      nodes[i].removeAttribute("dragged");
-
-    // Slide the dragged site back into its cell (may be the old or the new cell).
-    gTransformation.slideSiteTo(aSite, aSite.cell, {unfreeze: true});
-
-    this._draggedSite = null;
-  },
-
-  /**
-   * Checks whether we're responsible for a given drag event.
-   * @param aEvent The drag event to check.
-   * @return Whether we should handle this drag and drop operation.
-   */
-  isValid: function Drag_isValid(aEvent) {
-    let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
-
-    // Check that the drag data is non-empty.
-    // Can happen when dragging places folders.
-    if (!link || !link.url) {
-      return false;
-    }
-
-    // Check that we're not accepting URLs which would inherit the caller's
-    // principal (such as javascript: or data:).
-    return gLinkChecker.checkLoadURI(link.url);
-  },
-
-  /**
-   * Initializes the drag data for the current drag operation.
-   * @param aSite The site that's being dragged.
-   * @param aEvent The 'dragstart' event.
-   */
-  _setDragData: function Drag_setDragData(aSite, aEvent) {
-    let {url, title} = aSite;
-
-    let dt = aEvent.dataTransfer;
-    dt.mozCursor = "default";
-    dt.effectAllowed = "move";
-    dt.setData("text/plain", url);
-    dt.setData("text/uri-list", url);
-    dt.setData("text/x-moz-url", url + "\n" + title);
-    dt.setData("text/html", "<a href=\"" + url + "\">" + url + "</a>");
-
-    // Create and use an empty drag element. We don't want to use the default
-    // drag image with its default opacity.
-    let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
-    dragElement.classList.add("newtab-drag");
-    let scrollbox = document.getElementById("newtab-vertical-margin");
-    scrollbox.appendChild(dragElement);
-    dt.setDragImage(dragElement, 0, 0);
-
-    // After the 'dragstart' event has been processed we can remove the
-    // temporary drag element from the DOM.
-    setTimeout(() => scrollbox.removeChild(dragElement), 0);
-  }
-};
deleted file mode 100644
--- a/browser/base/content/newtab/dragDataHelper.js
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifdef 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/. */
-#endif
-
-var gDragDataHelper = {
-  get mimeType() {
-    return "text/x-moz-url";
-  },
-
-  getLinkFromDragEvent: function DragDataHelper_getLinkFromDragEvent(aEvent) {
-    let dt = aEvent.dataTransfer;
-    if (!dt || !dt.types.includes(this.mimeType)) {
-      return null;
-    }
-
-    let data = dt.getData(this.mimeType) || "";
-    let [url, title] = data.split(/[\r\n]+/);
-    return {url: url, title: title};
-  }
-};
deleted file mode 100644
--- a/browser/base/content/newtab/drop.js
+++ /dev/null
@@ -1,150 +0,0 @@
-#ifdef 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/. */
-#endif
-
-// A little delay that prevents the grid from being too sensitive when dragging
-// sites around.
-const DELAY_REARRANGE_MS = 100;
-
-/**
- * This singleton implements site dropping functionality.
- */
-var gDrop = {
-  /**
-   * The last drop target.
-   */
-  _lastDropTarget: null,
-
-  /**
-   * Handles the 'dragenter' event.
-   * @param aCell The drop target cell.
-   */
-  enter: function Drop_enter(aCell) {
-    this._delayedRearrange(aCell);
-  },
-
-  /**
-   * Handles the 'dragexit' event.
-   * @param aCell The drop target cell.
-   * @param aEvent The 'dragexit' event.
-   */
-  exit: function Drop_exit(aCell, aEvent) {
-    if (aEvent.dataTransfer && !aEvent.dataTransfer.mozUserCancelled) {
-      this._delayedRearrange();
-    } else {
-      // The drag operation has been cancelled.
-      this._cancelDelayedArrange();
-      this._rearrange();
-    }
-  },
-
-  /**
-   * Handles the 'drop' event.
-   * @param aCell The drop target cell.
-   * @param aEvent The 'dragexit' event.
-   */
-  drop: function Drop_drop(aCell, aEvent) {
-    // The cell that is the drop target could contain a pinned site. We need
-    // to find out where that site has gone and re-pin it there.
-    if (aCell.containsPinnedSite())
-      this._repinSitesAfterDrop(aCell);
-
-    // Pin the dragged or insert the new site.
-    this._pinDraggedSite(aCell, aEvent);
-
-    this._cancelDelayedArrange();
-
-    // Update the grid and move all sites to their new places.
-    gUpdater.updateGrid();
-  },
-
-  /**
-   * Re-pins all pinned sites in their (new) positions.
-   * @param aCell The drop target cell.
-   */
-  _repinSitesAfterDrop: function Drop_repinSitesAfterDrop(aCell) {
-    let sites = gDropPreview.rearrange(aCell);
-
-    // Filter out pinned sites.
-    let pinnedSites = sites.filter(function (aSite) {
-      return aSite && aSite.isPinned();
-    });
-
-    // Re-pin all shifted pinned cells.
-    pinnedSites.forEach(aSite => aSite.pin(sites.indexOf(aSite)));
-  },
-
-  /**
-   * Pins the dragged site in its new place.
-   * @param aCell The drop target cell.
-   * @param aEvent The 'dragexit' event.
-   */
-  _pinDraggedSite: function Drop_pinDraggedSite(aCell, aEvent) {
-    let index = aCell.index;
-    let draggedSite = gDrag.draggedSite;
-
-    if (draggedSite) {
-      // Pin the dragged site at its new place.
-      if (aCell != draggedSite.cell)
-        draggedSite.pin(index);
-    } else {
-      let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
-      if (link) {
-        // A new link was dragged onto the grid. Create it by pinning its URL.
-        gPinnedLinks.pin(link, index);
-
-        // Make sure the newly added link is not blocked.
-        gBlockedLinks.unblock(link);
-      }
-    }
-  },
-
-  /**
-   * Time a rearrange with a little delay.
-   * @param aCell The drop target cell.
-   */
-  _delayedRearrange: function Drop_delayedRearrange(aCell) {
-    // The last drop target didn't change so there's no need to re-arrange.
-    if (this._lastDropTarget == aCell)
-      return;
-
-    let self = this;
-
-    function callback() {
-      self._rearrangeTimeout = null;
-      self._rearrange(aCell);
-    }
-
-    this._cancelDelayedArrange();
-    this._rearrangeTimeout = setTimeout(callback, DELAY_REARRANGE_MS);
-
-    // Store the last drop target.
-    this._lastDropTarget = aCell;
-  },
-
-  /**
-   * Cancels a timed rearrange, if any.
-   */
-  _cancelDelayedArrange: function Drop_cancelDelayedArrange() {
-    if (this._rearrangeTimeout) {
-      clearTimeout(this._rearrangeTimeout);
-      this._rearrangeTimeout = null;
-    }
-  },
-
-  /**
-   * Rearrange all sites in the grid depending on the current drop target.
-   * @param aCell The drop target cell.
-   */
-  _rearrange: function Drop_rearrange(aCell) {
-    let sites = gGrid.sites;
-
-    // We need to rearrange the grid only if there's a current drop target.
-    if (aCell)
-      sites = gDropPreview.rearrange(aCell);
-
-    gTransformation.rearrangeSites(sites, {unfreeze: !aCell});
-  }
-};
deleted file mode 100644
--- a/browser/base/content/newtab/dropPreview.js
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifdef 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/. */
-#endif
-
-/**
- * This singleton provides the ability to re-arrange the current grid to
- * indicate the transformation that results from dropping a cell at a certain
- * position.
- */
-var gDropPreview = {
-  /**
-   * Rearranges the sites currently contained in the grid when a site would be
-   * dropped onto the given cell.
-   * @param aCell The drop target cell.
-   * @return The re-arranged array of sites.
-   */
-  rearrange: function DropPreview_rearrange(aCell) {
-    let sites = gGrid.sites;
-
-    // Insert the dragged site into the current grid.
-    this._insertDraggedSite(sites, aCell);
-
-    // After the new site has been inserted we need to correct the positions
-    // of all pinned tabs that have been moved around.
-    this._repositionPinnedSites(sites, aCell);
-
-    return sites;
-  },
-
-  /**
-   * Inserts the currently dragged site into the given array of sites.
-   * @param aSites The array of sites to insert into.
-   * @param aCell The drop target cell.
-   */
-  _insertDraggedSite: function DropPreview_insertDraggedSite(aSites, aCell) {
-    let dropIndex = aCell.index;
-    let draggedSite = gDrag.draggedSite;
-
-    // We're currently dragging a site.
-    if (draggedSite) {
-      let dragCell = draggedSite.cell;
-      let dragIndex = dragCell.index;
-
-      // Move the dragged site into its new position.
-      if (dragIndex != dropIndex) {
-        aSites.splice(dragIndex, 1);
-        aSites.splice(dropIndex, 0, draggedSite);
-      }
-    // We're handling an external drag item.
-    } else {
-      aSites.splice(dropIndex, 0, null);
-    }
-  },
-
-  /**
-   * Correct the position of all pinned sites that might have been moved to
-   * different positions after the dragged site has been inserted.
-   * @param aSites The array of sites containing the dragged site.
-   * @param aCell The drop target cell.
-   */
-  _repositionPinnedSites:
-    function DropPreview_repositionPinnedSites(aSites, aCell) {
-
-    // Collect all pinned sites.
-    let pinnedSites = this._filterPinnedSites(aSites, aCell);
-
-    // Correct pinned site positions.
-    pinnedSites.forEach(function (aSite) {
-      aSites[aSites.indexOf(aSite)] = aSites[aSite.cell.index];
-      aSites[aSite.cell.index] = aSite;
-    }, this);
-
-    // There might be a pinned cell that got pushed out of the grid, try to
-    // sneak it in by removing a lower-priority cell.
-    if (this._hasOverflowedPinnedSite(aSites, aCell))
-      this._repositionOverflowedPinnedSite(aSites, aCell);
-  },
-
-  /**
-   * Filter pinned sites out of the grid that are still on their old positions
-   * and have not moved.
-   * @param aSites The array of sites to filter.
-   * @param aCell The drop target cell.
-   * @return The filtered array of sites.
-   */
-  _filterPinnedSites: function DropPreview_filterPinnedSites(aSites, aCell) {
-    let draggedSite = gDrag.draggedSite;
-
-    // When dropping on a cell that contains a pinned site make sure that all
-    // pinned cells surrounding the drop target are moved as well.
-    let range = this._getPinnedRange(aCell);
-
-    return aSites.filter(function (aSite, aIndex) {
-      // The site must be valid, pinned and not the dragged site.
-      if (!aSite || aSite == draggedSite || !aSite.isPinned())
-        return false;
-
-      let index = aSite.cell.index;
-
-      // If it's not in the 'pinned range' it's a valid pinned site.
-      return (index > range.end || index < range.start);
-    });
-  },
-
-  /**
-   * Determines the range of pinned sites surrounding the drop target cell.
-   * @param aCell The drop target cell.
-   * @return The range of pinned cells.
-   */
-  _getPinnedRange: function DropPreview_getPinnedRange(aCell) {
-    let dropIndex = aCell.index;
-    let range = {start: dropIndex, end: dropIndex};
-
-    // We need a pinned range only when dropping on a pinned site.
-    if (aCell.containsPinnedSite()) {
-      let links = gPinnedLinks.links;
-
-      // Find all previous siblings of the drop target that are pinned as well.
-      while (range.start && links[range.start - 1])
-        range.start--;
-
-      let maxEnd = links.length - 1;
-
-      // Find all next siblings of the drop target that are pinned as well.
-      while (range.end < maxEnd && links[range.end + 1])
-        range.end++;
-    }
-
-    return range;
-  },
-
-  /**
-   * Checks if the given array of sites contains a pinned site that has
-   * been pushed out of the grid.
-   * @param aSites The array of sites to check.
-   * @param aCell The drop target cell.
-   * @return Whether there is an overflowed pinned cell.
-   */
-  _hasOverflowedPinnedSite:
-    function DropPreview_hasOverflowedPinnedSite(aSites, aCell) {
-
-    // If the drop target isn't pinned there's no way a pinned site has been
-    // pushed out of the grid so we can just exit here.
-    if (!aCell.containsPinnedSite())
-      return false;
-
-    let cells = gGrid.cells;
-
-    // No cells have been pushed out of the grid, nothing to do here.
-    if (aSites.length <= cells.length)
-      return false;
-
-    let overflowedSite = aSites[cells.length];
-
-    // Nothing to do if the site that got pushed out of the grid is not pinned.
-    return (overflowedSite && overflowedSite.isPinned());
-  },
-
-  /**
-   * We have a overflowed pinned site that we need to re-position so that it's
-   * visible again. We try to find a lower-priority cell (empty or containing
-   * an unpinned site) that we can move it to.
-   * @param aSites The array of sites.
-   * @param aCell The drop target cell.
-   */
-  _repositionOverflowedPinnedSite:
-    function DropPreview_repositionOverflowedPinnedSite(aSites, aCell) {
-
-    // Try to find a lower-priority cell (empty or containing an unpinned site).
-    let index = this._indexOfLowerPrioritySite(aSites, aCell);
-
-    if (index > -1) {
-      let cells = gGrid.cells;
-      let dropIndex = aCell.index;
-
-      // Move all pinned cells to their new positions to let the overflowed
-      // site fit into the grid.
-      for (let i = index + 1, lastPosition = index; i < aSites.length; i++) {
-        if (i != dropIndex) {
-          aSites[lastPosition] = aSites[i];
-          lastPosition = i;
-        }
-      }
-
-      // Finally, remove the overflowed site from its previous position.
-      aSites.splice(cells.length, 1);
-    }
-  },
-
-  /**
-   * Finds the index of the last cell that is empty or contains an unpinned
-   * site. These are considered to be of a lower priority.
-   * @param aSites The array of sites.
-   * @param aCell The drop target cell.
-   * @return The cell's index.
-   */
-  _indexOfLowerPrioritySite:
-    function DropPreview_indexOfLowerPrioritySite(aSites, aCell) {
-
-    let cells = gGrid.cells;
-    let dropIndex = aCell.index;
-
-    // Search (beginning with the last site in the grid) for a site that is
-    // empty or unpinned (an thus lower-priority) and can be pushed out of the
-    // grid instead of the pinned site.
-    for (let i = cells.length - 1; i >= 0; i--) {
-      // The cell that is our drop target is not a good choice.
-      if (i == dropIndex)
-        continue;
-
-      let site = aSites[i];
-
-      // We can use the cell only if it's empty or the site is un-pinned.
-      if (!site || !site.isPinned())
-        return i;
-    }
-
-    return -1;
-  }
-};
deleted file mode 100644
--- a/browser/base/content/newtab/dropTargetShim.js
+++ /dev/null
@@ -1,232 +0,0 @@
-#ifdef 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/. */
-#endif
-
-/**
- * This singleton provides a custom drop target detection. We need this because
- * the default DnD target detection relies on the cursor's position. We want
- * to pick a drop target based on the dragged site's position.
- */
-var gDropTargetShim = {
-  /**
-   * Cache for the position of all cells, cleaned after drag finished.
-   */
-  _cellPositions: null,
-
-  /**
-   * The last drop target that was hovered.
-   */
-  _lastDropTarget: null,
-
-  /**
-   * Initializes the drop target shim.
-   */
-  init: function () {
-    gGrid.node.addEventListener("dragstart", this, true);
-  },
-
-  /**
-   * Add all event listeners needed during a drag operation.
-   */
-  _addEventListeners: function () {
-    gGrid.node.addEventListener("dragend", this);
-
-    let docElement = document.documentElement;
-    docElement.addEventListener("dragover", this);
-    docElement.addEventListener("dragenter", this);
-    docElement.addEventListener("drop", this);
-  },
-
-  /**
-   * Remove all event listeners that were needed during a drag operation.
-   */
-  _removeEventListeners: function () {
-    gGrid.node.removeEventListener("dragend", this);
-
-    let docElement = document.documentElement;
-    docElement.removeEventListener("dragover", this);
-    docElement.removeEventListener("dragenter", this);
-    docElement.removeEventListener("drop", this);
-  },
-
-  /**
-   * Handles all shim events.
-   */
-  handleEvent: function (aEvent) {
-    switch (aEvent.type) {
-      case "dragstart":
-        this._dragstart(aEvent);
-        break;
-      case "dragenter":
-        aEvent.preventDefault();
-        break;
-      case "dragover":
-        this._dragover(aEvent);
-        break;
-      case "drop":
-        this._drop(aEvent);
-        break;
-      case "dragend":
-        this._dragend(aEvent);
-        break;
-    }
-  },
-
-  /**
-   * Handles the 'dragstart' event.
-   * @param aEvent The 'dragstart' event.
-   */
-  _dragstart: function (aEvent) {
-    if (aEvent.target.classList.contains("newtab-link")) {
-      gGrid.lock();
-      this._addEventListeners();
-    }
-  },
-
-  /**
-   * Handles the 'dragover' event.
-   * @param aEvent The 'dragover' event.
-   */
-  _dragover: function (aEvent) {
-    // XXX bug 505521 - Use the dragover event to retrieve the
-    //                  current mouse coordinates while dragging.
-    let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode;
-    gDrag.drag(sourceNode._newtabSite, aEvent);
-
-    // Find the current drop target, if there's one.
-    this._updateDropTarget(aEvent);
-
-    // If we have a valid drop target,
-    // let the drag-and-drop service know.
-    if (this._lastDropTarget) {
-      aEvent.preventDefault();
-    }
-  },
-
-  /**
-   * Handles the 'drop' event.
-   * @param aEvent The 'drop' event.
-   */
-  _drop: function (aEvent) {
-    // We're accepting all drops.
-    aEvent.preventDefault();
-
-    // remember that drop event was seen, this explicitly
-    // assumes that drop event preceeds dragend event
-    this._dropSeen = true;
-
-    // Make sure to determine the current drop target
-    // in case the dragover event hasn't been fired.
-    this._updateDropTarget(aEvent);
-
-    // A site was successfully dropped.
-    this._dispatchEvent(aEvent, "drop", this._lastDropTarget);
-  },
-
-  /**
-   * Handles the 'dragend' event.
-   * @param aEvent The 'dragend' event.
-   */
-  _dragend: function (aEvent) {
-    if (this._lastDropTarget) {
-      if (aEvent.dataTransfer.mozUserCancelled || !this._dropSeen) {
-        // The drag operation was cancelled or no drop event was generated
-        this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
-        this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
-      }
-
-      // Clean up.
-      this._lastDropTarget = null;
-      this._cellPositions = null;
-    }
-
-    this._dropSeen = false;
-    gGrid.unlock();
-    this._removeEventListeners();
-  },
-
-  /**
-   * Tries to find the current drop target and will fire
-   * appropriate dragenter, dragexit, and dragleave events.
-   * @param aEvent The current drag event.
-   */
-  _updateDropTarget: function (aEvent) {
-    // Let's see if we find a drop target.
-    let target = this._findDropTarget(aEvent);
-
-    if (target != this._lastDropTarget) {
-      if (this._lastDropTarget)
-        // We left the last drop target.
-        this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
-
-      if (target)
-        // We're now hovering a (new) drop target.
-        this._dispatchEvent(aEvent, "dragenter", target);
-
-      if (this._lastDropTarget)
-        // We left the last drop target.
-        this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
-
-      this._lastDropTarget = target;
-    }
-  },
-
-  /**
-   * Determines the current drop target by matching the dragged site's position
-   * against all cells in the grid.
-   * @return The currently hovered drop target or null.
-   */
-  _findDropTarget: function () {
-    // These are the minimum intersection values - we want to use the cell if
-    // the site is >= 50% hovering its position.
-    let minWidth = gDrag.cellWidth / 2;
-    let minHeight = gDrag.cellHeight / 2;
-
-    let cellPositions = this._getCellPositions();
-    let rect = gTransformation.getNodePosition(gDrag.draggedSite.node);
-
-    // Compare each cell's position to the dragged site's position.
-    for (let i = 0; i < cellPositions.length; i++) {
-      let inter = rect.intersect(cellPositions[i].rect);
-
-      // If the intersection is big enough we found a drop target.
-      if (inter.width >= minWidth && inter.height >= minHeight)
-        return cellPositions[i].cell;
-    }
-
-    // No drop target found.
-    return null;
-  },
-
-  /**
-   * Gets the positions of all cell nodes.
-   * @return The (cached) cell positions.
-   */
-  _getCellPositions: function DropTargetShim_getCellPositions() {
-    if (this._cellPositions)
-      return this._cellPositions;
-
-    return this._cellPositions = gGrid.cells.map(function (cell) {
-      return {cell: cell, rect: gTransformation.getNodePosition(cell.node)};
-    });
-  },
-
-  /**
-   * Dispatches a custom DragEvent on the given target node.
-   * @param aEvent The source event.
-   * @param aType The event type.
-   * @param aTarget The target node that receives the event.
-   */
-  _dispatchEvent: function (aEvent, aType, aTarget) {
-    let node = aTarget.node;
-    let event = document.createEvent("DragEvent");
-
-    // The event should not bubble to prevent recursion.
-    event.initDragEvent(aType, false, true, window, 0, 0, 0, 0, 0, false, false,
-                        false, false, 0, node, aEvent.dataTransfer);
-
-    node.dispatchEvent(event);
-  }
-};
deleted file mode 100644
--- a/browser/base/content/newtab/grid.js
+++ /dev/null
@@ -1,295 +0,0 @@
-#ifdef 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/. */
-#endif
-
-/**
- * Define various fixed dimensions
- */
-const GRID_BOTTOM_EXTRA = 7; // title's line-height extends 7px past the margin
-const GRID_WIDTH_EXTRA = 1; // provide 1px buffer to allow for rounding error
-
-/**
- * This singleton represents the grid that contains all sites.
- */
-var gGrid = {
-  /**
-   * The DOM node of the grid.
-   */
-  _node: null,
-  _gridDefaultContent: null,
-  get node() { return this._node; },
-
-  /**
-   * The cached DOM fragment for sites.
-   */
-  _siteFragment: null,
-
-  /**
-   * All cells contained in the grid.
-   */
-  _cells: [],
-  get cells() { return this._cells; },
-
-  /**
-   * All sites contained in the grid's cells. Sites may be empty.
-   */
-  get sites() { return this.cells.map(cell => cell.site); },
-
-  // Tells whether the grid has already been initialized.
-  get ready() { return !!this._ready; },
-
-  // Returns whether the page has finished loading yet.
-  get isDocumentLoaded() { return document.readyState == "complete"; },
-
-  /**
-   * Initializes the grid.
-   * @param aSelector The query selector of the grid.
-   */
-  init: function Grid_init() {
-    this._node = document.getElementById("newtab-grid");
-    this._gridDefaultContent = this._node.lastChild;
-    this._createSiteFragment();
-
-    gLinks.populateCache(() => {
-      this._refreshGrid();
-      this._ready = true;
-
-      // If fetching links took longer than loading the page itself then
-      // we need to resize the grid as that was blocked until now.
-      // We also want to resize now if the page was already loaded when
-      // initializing the grid (the user toggled the page).
-      this._resizeGrid();
-
-      addEventListener("resize", this);
-    });
-
-    // Resize the grid as soon as the page loads.
-    if (!this.isDocumentLoaded) {
-      addEventListener("load", this);
-    }
-  },
-
-  /**
-   * Creates a new site in the grid.
-   * @param aLink The new site's link.
-   * @param aCell The cell that will contain the new site.
-   * @return The newly created site.
-   */
-  createSite: function Grid_createSite(aLink, aCell) {
-    let node = aCell.node;
-    node.appendChild(this._siteFragment.cloneNode(true));
-    return new Site(node.firstElementChild, aLink);
-  },
-
-  /**
-   * Handles all grid events.
-   */
-  handleEvent: function Grid_handleEvent(aEvent) {
-    switch (aEvent.type) {
-      case "load":
-      case "resize":
-        this._resizeGrid();
-        break;
-    }
-  },
-
-  /**
-   * Locks the grid to block all pointer events.
-   */
-  lock: function Grid_lock() {
-    this.node.setAttribute("locked", "true");
-  },
-
-  /**
-   * Unlocks the grid to allow all pointer events.
-   */
-  unlock: function Grid_unlock() {
-    this.node.removeAttribute("locked");
-  },
-
-  /**
-   * Renders and resizes the gird. _resizeGrid() call is needed to ensure
-   * that scrollbar disappears when the bottom row becomes empty following
-   * the block action, or tile display is turmed off via cog menu
-   */
-
-  refresh() {
-    this._refreshGrid();
-    this._resizeGrid();
-  },
-
-  /**
-   * Renders the grid, including cells and sites.
-   */
-  _refreshGrid() {
-    let cell = document.createElementNS(HTML_NAMESPACE, "div");
-    cell.classList.add("newtab-cell");
-
-    // Creates all the cells up to the maximum
-    let fragment = document.createDocumentFragment();
-    for (let i = 0; i < gGridPrefs.gridColumns * gGridPrefs.gridRows; i++) {
-      fragment.appendChild(cell.cloneNode(true));
-    }
-
-    // Create cells.
-    let cells = Array.from(fragment.childNodes, (cell) => new Cell(this, cell));
-
-    // Fetch links.
-    let links = gLinks.getLinks();
-
-    // Create sites.
-    let numLinks = Math.min(links.length, cells.length);
-    let hasHistoryTiles = false;
-    for (let i = 0; i < numLinks; i++) {
-      if (links[i]) {
-        this.createSite(links[i], cells[i]);
-        if (links[i].type == "history") {
-          hasHistoryTiles = true;
-        }
-      }
-    }
-
-    this._cells = cells;
-    while (this._gridDefaultContent.nextSibling) {
-      this._gridDefaultContent.nextSibling.remove();
-    }
-    this._node.appendChild(fragment);
-
-    document.getElementById("topsites-heading").textContent =
-      newTabString(hasHistoryTiles ? "userTopSites.heading" : "defaultTopSites.heading");
-  },
-
-  /**
-   * Calculate the height for a number of rows up to the maximum rows
-   * @param rows Number of rows defaulting to the max
-   */
-  _computeHeight: function Grid_computeHeight(aRows) {
-    let {gridRows} = gGridPrefs;
-    aRows = aRows === undefined ? gridRows : Math.min(gridRows, aRows);
-    return aRows * this._cellHeight + GRID_BOTTOM_EXTRA;
-  },
-
-  /**
-   * Creates the DOM fragment that is re-used when creating sites.
-   */
-  _createSiteFragment: function Grid_createSiteFragment() {
-    let site = document.createElementNS(HTML_NAMESPACE, "div");
-    site.classList.add("newtab-site");
-    site.setAttribute("draggable", "true");
-
-    let link = document.createElement("a");
-    link.className = "newtab-link";
-    site.appendChild(link);
-
-    let thumbnailPlaceHolder = document.createElement("span");
-    thumbnailPlaceHolder.className = "newtab-thumbnail placeholder";
-    link.appendChild(thumbnailPlaceHolder);
-
-    let thumbnail = document.createElement("img");
-    thumbnail.className = "newtab-thumbnail thumbnail";
-    link.appendChild(thumbnail);
-
-    let enhancedContent = document.createElement("img");
-    enhancedContent.className = "newtab-thumbnail enhanced-content";
-    link.appendChild(enhancedContent);
-
-    let title = document.createElement("span");
-    title.className = "newtab-title";
-    link.appendChild(title);
-
-    let pinButton = document.createElement("input");
-    pinButton.type = "button";
-    pinButton.title = newTabString("pin");
-    pinButton.className = "newtab-control newtab-control-pin";
-    site.appendChild(pinButton);
-
-    let removeButton = document.createElement("input");
-    removeButton.type = "button";
-    removeButton.title = newTabString("block");
-    removeButton.className = "newtab-control newtab-control-block";
-    site.appendChild(removeButton);
-
-    this._siteFragment = document.createDocumentFragment();
-    this._siteFragment.appendChild(site);
-  },
-
-  /**
-   * Test a tile at a given position for being pinned or history
-   * @param position Position in sites array
-   */
-  _isHistoricalTile: function Grid_isHistoricalTile(aPos) {
-    let site = this.sites[aPos];
-    return site && (site.isPinned() || site.link && site.link.type == "history");
-  },
-
-  /**
-   * Make sure the correct number of rows and columns are visible
-   */
-  _resizeGrid: function Grid_resizeGrid() {
-    // If we're somehow called before the page has finished loading,
-    // let's bail out to avoid caching zero heights and widths.
-    // We'll be called again when DOMContentLoaded fires.
-    // Same goes for the grid if that's not ready yet.
-    if (!this.isDocumentLoaded || !this._ready) {
-      return;
-    }
-
-    // Save the cell's computed height/width including margin and border
-    if (this._cellHeight === undefined) {
-      let refCell = document.querySelector(".newtab-cell");
-      let style = getComputedStyle(refCell);
-      this._cellHeight = refCell.offsetHeight +
-        parseFloat(style.marginTop) + parseFloat(style.marginBottom);
-      this._cellWidth = refCell.offsetWidth +
-        parseFloat(style.marginLeft) + parseFloat(style.marginRight);
-    }
-
-    let searchContainer = document.querySelector("#newtab-search-container");
-    // Save search-container margin height
-    if (this._searchContainerMargin === undefined) {
-      let style = getComputedStyle(searchContainer);
-      this._searchContainerMargin = parseFloat(style.marginBottom) +
-                                    parseFloat(style.marginTop);
-    }
-
-    // Find the number of rows we can place into view port
-    let availHeight = document.documentElement.clientHeight -
-                      searchContainer.offsetHeight - this._searchContainerMargin;
-    let visibleRows = Math.floor(availHeight / this._cellHeight);
-
-    // Find the number of columns that fit into view port
-    let maxGridWidth = gGridPrefs.gridColumns * this._cellWidth + GRID_WIDTH_EXTRA;
-    // available width is current grid width, but no greater than maxGridWidth
-    let availWidth = Math.min(document.querySelector("#newtab-grid").clientWidth,
-                              maxGridWidth);
-    // finally get the number of columns we can fit into view port
-    let gridColumns = Math.floor(availWidth / this._cellWidth);
-    // walk sites backwords until a pinned or history tile is found or visibleRows reached
-    let tileIndex = Math.min(gGridPrefs.gridRows * gridColumns, this.sites.length) - 1;
-    while (tileIndex >= visibleRows * gridColumns) {
-      if (this._isHistoricalTile(tileIndex)) {
-        break;
-      }
-      tileIndex--;
-    }
-
-    // Compute the actual number of grid rows we will display (potentially
-    // with a scroll bar). tileIndex now points to a historical tile with
-    // heighest index or to the last index of the visible row, if none found
-    // Dividing tileIndex by number of tiles in a column gives the rows
-    let gridRows = Math.floor(tileIndex / gridColumns) + 1;
-
-    // we need to set grid width, for otherwise the scrollbar may shrink
-    // the grid when shown and cause grid layout to be different from
-    // what being computed above. This, in turn, may cause scrollbar shown
-    // for directory tiles, and introduce jitter when grid width is aligned
-    // exactly on the column boundary
-    this._node.style.width = gridColumns * this._cellWidth + "px";
-    this._node.style.maxWidth = gGridPrefs.gridColumns * this._cellWidth +
-                                GRID_WIDTH_EXTRA + "px";
-    this._node.style.height = this._computeHeight() + "px";
-    this._node.style.maxHeight = this._computeHeight(gridRows) + "px";
-  }
-};
deleted file mode 100644
--- a/browser/base/content/newtab/newTab.css
+++ /dev/null
@@ -1,512 +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 {
-  width: 100%;
-  height: 100%;
-}
-
-body {
-  font: message-box;
-  width: 100%;
-  height: 100%;
-  padding: 0;
-  margin: 0;
-  background-color: #F9F9FA;
-  display: -moz-box;
-  position: relative;
-  -moz-box-flex: 1;
-  -moz-user-focus: normal;
-  -moz-box-orient: vertical;
-}
-
-input {
-  font: message-box;
-  font-size: 16px;
-}
-
-input[type=button] {
-  cursor: pointer;
-}
-
-/* UNDO */
-#newtab-undo-container {
-  transition: opacity 100ms ease-out;
-  -moz-box-align: center;
-  -moz-box-pack: center;
-  position: relative;
-  left: -50%;
-}
-
-#newtab-undo-container[undo-disabled] {
-  opacity: 0;
-  pointer-events: none;
-}
-
-/* CUSTOMIZE */
-#newtab-customize-button {
-  position: absolute;
-  top: 10px;
-  right: 20px;
-  z-index: 101;
-}
-
-#newtab-customize-button:dir(rtl) {
-  left: 20px;
-  right: auto;
-}
-
-/* MARGINS */
-#newtab-vertical-margin {
-  display: -moz-box;
-  position: relative;
-  -moz-box-flex: 1;
-  -moz-box-orient: vertical;
-}
-
-#newtab-margin-undo-container {
-  display: -moz-box;
-  left: 50%;
-  position: absolute;
-  top: 6px;
-  z-index: 1;
-}
-
-#newtab-margin-undo-container:dir(rtl) {
-  left: auto;
-  right: 6px;
-}
-
-#newtab-undo-close-button:dir(rtl) {
-  float:left;
-}
-
-#newtab-horizontal-margin {
-  display: -moz-box;
-  -moz-box-flex: 1;
-}
-
-#newtab-margin-top,
-#newtab-margin-bottom {
-  display: -moz-box;
-  position: relative;
-}
-
-#newtab-margin-top {
-  -moz-box-flex: 1;
-}
-
-#newtab-margin-bottom {
-  -moz-box-flex: 2;
-}
-
-.newtab-side-margin {
-  min-width: 10px;
-  -moz-box-flex: 1;
-}
-
-/* GRID */
-#newtab-grid {
-  -moz-box-flex: 5;
-  overflow: hidden;
-  text-align: center;
-  transition: 100ms ease-out;
-  transition-property: opacity;
-}
-
-#newtab-grid[page-disabled] {
-  opacity: 0;
-}
-
-#newtab-grid[locked],
-#newtab-grid[page-disabled] {
-  pointer-events: none;
-}
-
-body:not(.compact) #topsites-heading {
-  display: none;
-}
-
-/*
- * If you change the sizes here, make sure you
- * change the preferences:
- * toolkit.pageThumbs.minWidth
- * toolkit.pageThumbs.minHeight
- */
-/* CELLS */
-.newtab-cell {
-  display: -moz-box;
-  height: 210px;
-  margin: 20px 10px 35px;
-  width: 290px;
-}
-
-body.compact .newtab-cell {
-  width: 110px;
-  height: 110px;
-  margin: 12px;
-}
-
-/* SITES */
-.newtab-site {
-  position: relative;
-  -moz-box-flex: 1;
-  transition: 100ms ease-out;
-  transition-property: top, left, opacity;
-}
-
-.newtab-site[frozen] {
-  position: absolute;
-  pointer-events: none;
-}
-
-.newtab-site[dragged] {
-  transition-property: none;
-  z-index: 10;
-}
-
-/* LINK + THUMBNAILS */
-.newtab-link,
-.newtab-thumbnail {
-  position: absolute;
-  left: 0;
-  top: 0;
-  right: 0;
-  bottom: 0;
-}
-
-/* TITLES */
-.newtab-title {
-  overflow: hidden;
-  position: absolute;
-  right: 0;
-  text-align: center;
-  bottom: 0;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-  vertical-align: middle;
-}
-
-.newtab-title {
-  left: 0;
-  padding: 0 4px;
-}
-
-/* CONTROLS */
-.newtab-control {
-  position: absolute;
-  opacity: 0;
-  transition: opacity 100ms ease-out;
-}
-
-.newtab-control:-moz-focusring,
-.newtab-cell:not([ignorehover]) > .newtab-site:hover > .newtab-control {
-  opacity: 1;
-}
-
-.newtab-control[dragged] {
-  opacity: 0 !important;
-}
-
-@media (-moz-touch-enabled) {
-  .newtab-control {
-    opacity: 1;
-  }
-}
-
-/* DRAG & DROP */
-
-/*
- * This is just a temporary drag element used for dataTransfer.setDragImage()
- * so that we can use custom drag images and elements. It needs an opacity of
- * 0.01 so that the core code detects that it's in fact a visible element.
- */
-.newtab-drag {
-  width: 1px;
-  height: 1px;
-  background-color: #fff;
-  opacity: 0.01;
-}
-
-/* SEARCH */
-#newtab-search-container {
-  display: -moz-box;
-  position: relative;
-  -moz-box-pack: center;
-  margin: 55px 0 15px;
-}
-
-body.compact #newtab-search-container {
-  margin-top: 0;
-  margin-bottom: 80px;
-}
-
-#newtab-search-container[page-disabled] {
-  opacity: 0;
-  pointer-events: none;
-}
-
-#newtab-search-form {
-  display: -moz-box;
-  position: relative;
-  height: 36px;
-  -moz-box-flex: 1;
-  max-width: 600px; /* 2 * (290 cell width + 10 cell margin) */
-}
-
-#newtab-search-icon {
-  width: 35px;
-  height: 35px;
-  background: url("chrome://browser/skin/search-glass.svg") no-repeat 12px center/16px;
-  fill: rgba(12, 12, 13, 0.4);
-  -moz-context-properties: fill;
-  position: absolute;
-  offset-inline-start: 0;
-}
-
-#newtab-search-text {
-  -moz-box-flex: 1;
-  border: 1px solid rgba(0, 0, 0, 0.15);
-  border-radius: 3px;
-  box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
-  color: inherit;
-  padding: 0;
-  padding-inline-end: 36px;
-  padding-inline-start: 35px;
-  width: 100%;
-  font-size: 15px;
-}
-
-#newtab-search-text:active,
-#newtab-search-text:focus {
-  border-color: #0A84FF;
-  box-shadow: 0 0 0 2px #0A84FF;
-}
-
-#newtab-search-submit {
-  offset-inline-end: 0;
-  color: transparent;
-  background: url("chrome://browser/skin/forward.svg") no-repeat center center;
-  -moz-context-properties: fill;
-  fill: rgba(12, 12, 13, 0.4);
-  position: absolute;
-  border: 0;
-  border-radius: 0 3px 3px 0;
-  background-size: 16px 16px;
-  height: 100%;
-  width: 36px;
-}
-
-#newtab-search-submit:dir(rtl) {
-  transform: scaleX(-1);
-}
-
-#newtab-search-submit:focus, #newtab-search-submit:hover {
-  background-color: rgba(12, 12, 13, 0.1);
-  cursor: pointer;
-}
-
-#newtab-search-submit:active {
-  background-color: rgba(12, 12, 13, 0.15);
-}
-
-/* CUSTOMIZE */
-#newtab-customize-overlay {
-  opacity: 0;
-  display: none;
-  width: 100%;
-  height: 100%;
-  background: #F9F9F9;
-  z-index: 100;
-  position: fixed;
-  transition: opacity .07s linear;
-}
-
-.newtab-customize-panel-container {
-  position: absolute;
-  margin-right: 40px;
-  right: 0;
-}
-
-.newtab-customize-panel-container:dir(rtl) {
-  right: auto;
-  left: 0;
-}
-
-#newtab-customize-panel {
-  z-index: 999;
-  margin-top: 55px;
-  min-width: 270px;
-  position: absolute;
-  top: 100%;
-  right: -25px;
-  filter: drop-shadow(0 0 1px rgba(0,0,0,0.4)) drop-shadow(0 3px 4px rgba(0,0,0,0.4));
-  transition: all 200ms ease-in-out;
-  transform-origin: top right;
-  transform: translate(-30px, -20px) scale(0) translate(30px, 20px);
-}
-
-#newtab-customize-panel:dir(rtl) {
-  transform-origin: 40px top 20px;
-}
-
-#newtab-customize-panel:dir(rtl),
-#newtab-customize-panel-anchor:dir(rtl) {
-  left: 15px;
-  right: auto;
-}
-
-#newtab-customize-panel[open="true"] {
-  transform: translate(-30px, -20px) scale(1) translate(30px, 20px);
-}
-
-#newtab-customize-panel-anchor {
-  width: 18px;
-  height: 18px;
-  background-color: white;
-  transform: rotate(45deg);
-  position: absolute;
-  top: -6px;
-  right: 15px;
-}
-
-#newtab-customize-title {
-  color: #7A7A7A;
-  font-size: 14px;
-  background-color: #FFFFFF;
-  line-height: 25px;
-  padding: 15px;
-  font-weight: 600;
-  cursor: default;
-  border-radius: 5px 5px 0px 0px;
-  max-width: 300px;
-  overflow: hidden;
-  display: table-cell;
-  border-top: none;
-}
-
-#newtab-customize-panel-inner-wrapper {
-  background-color: #FFFFFF;
-  border-radius: 6px;
-  overflow: hidden;
-}
-
-#newtab-customize-title > label {
-  cursor: default;
-}
-
-#newtab-customize-panel > .panel-arrowcontainer > .panel-arrowcontent {
-  padding: 0;
-}
-
-.newtab-customize-panel-item {
-  line-height: 25px;
-  padding: 15px;
-  padding-inline-start: 40px;
-  font-size: 14px;
-  cursor: pointer;
-  max-width: 300px;
-}
-
-.newtab-customize-panel-item:not(:first-child) {
-  border-top: 1px solid threedshadow;
-}
-
-.newtab-customize-panel-subitem > label,
-.newtab-customize-panel-item > label,
-.newtab-customize-complex-option {
-  padding: 0;
-  margin: 0;
-  cursor: pointer;
-}
-
-.newtab-customize-panel-item,
-.newtab-customize-complex-option {
-  display: block;
-  text-align: start;
-  background-color: #F9F9F9;
-}
-
-.newtab-customize-panel-item[selected]:dir(rtl){
-  background-position: right 15px center;
-}
-
-.newtab-customize-complex-option:hover > .selectable:not([selected]):dir(rtl),
-.selectable:not([selected]):hover:dir(rtl) {
-  background-position: right 15px center;
-}
-
-.newtab-customize-panel-item:not([selected]),
-.newtab-customize-panel-subitem:not([selected]){
-  color: #7A7A7A;
-}
-
-.newtab-customize-panel-item:not([selected]):hover {
-  color: #FFFFFF;
-  background-color: #4A90E2
-}
-
-.newtab-customize-complex-option:hover > .selectable:not([selected]),
-.selectable:not([selected]):hover {
-  background: url("chrome://global/skin/menu/shared-menu-check-hover.svg") no-repeat #FFFFFF;
-  background-size: 16px 16px;
-  background-position: 15px 15px;
-  color: #171F26;
-}
-
-.newtab-customize-complex-option:hover > .selectable:not([selected]) + .newtab-customize-panel-subitem {
-  background-color: #FFFFFF;
-}
-
-.newtab-customize-panel-item[selected] {
-  background: url("chrome://global/skin/menu/shared-menu-check-active.svg") no-repeat transparent;
-  background-size: 16px 16px;
-  background-position: 15px 15px;
-  color: black;
-  font-weight: 600;
-}
-
-.newtab-customize-panel-subitem > .checkbox {
-  width: 18px;
-  height: 18px;
-  background-color: #FFFFFF;
-  border: solid 1px threedshadow;
-}
-
-.newtab-customize-panel-subitem[selected] > .checkbox {
-  background: url("chrome://global/skin/menu/shared-menu-check-black.svg") no-repeat #FFFFFF;
-  background-size: 9px 9px;
-  background-position: center;
-  color: #333333;
-}
-
-.newtab-customize-panel-subitem {
-  font-size: 12px;
-  padding: 0px 15px 15px 15px;
-  padding-inline-start: 40px;
-  display: block;
-  max-width: 300px;
-}
-
-.newtab-customize-panel-subitem > label {
-  padding: 0px 10px;
-  line-height: 20px;
-  vertical-align: middle;
-  max-width: 225px;
-}
-
-.newtab-customize-panel-superitem {
-  line-height: 20px;
-  border-bottom: medium none !important;
-  padding: 15px 15px 10px 15px;
-  padding-inline-start: 40px;
-  border-top: 1px solid threedshadow;
-}
-
-.contentSearchSuggestionTable {
-  font: message-box;
-  font-size: 16px;
-  border: 0;
-  transform: translateY(2px);
-}
deleted file mode 100644
--- a/browser/base/content/newtab/newTab.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-ChromeUtils.import("resource://gre/modules/PageThumbs.jsm");
-ChromeUtils.import("resource://gre/modules/BackgroundPageThumbs.jsm");
-ChromeUtils.import("resource://gre/modules/NewTabUtils.jsm");
-
-ChromeUtils.defineModuleGetter(this, "Rect",
-  "resource://gre/modules/Geometry.jsm");
-ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
-  "resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-var {
-  links: gLinks,
-  allPages: gAllPages,
-  linkChecker: gLinkChecker,
-  pinnedLinks: gPinnedLinks,
-  blockedLinks: gBlockedLinks,
-  gridPrefs: gGridPrefs
-} = NewTabUtils;
-
-XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
-  return Services.strings.
-    createBundle("chrome://browser/locale/newTab.properties");
-});
-
-function newTabString(name, args) {
-  let stringName = "newtab." + name;
-  if (!args) {
-    return gStringBundle.GetStringFromName(stringName);
-  }
-  return gStringBundle.formatStringFromName(stringName, args, args.length);
-}
-
-function inPrivateBrowsingMode() {
-  return PrivateBrowsingUtils.isContentWindowPrivate(window);
-}
-
-const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
-const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-const TILES_EXPLAIN_LINK = "https://support.mozilla.org/kb/how-do-tiles-work-firefox";
-const TILES_INTRO_LINK = "https://www.mozilla.org/firefox/tiles/";
-const TILES_PRIVACY_LINK = "https://www.mozilla.org/privacy/";
-
-#include transformations.js
-#include page.js
-#include grid.js
-#include cells.js
-#include sites.js
-#include drag.js
-#include dragDataHelper.js
-#include drop.js
-#include dropTargetShim.js
-#include dropPreview.js
-#include updater.js
-#include undo.js
-#include search.js
-#include customize.js
-
-// Everything is loaded. Initialize the New Tab Page.
-gPage.init();
deleted file mode 100644
--- a/browser/base/content/newtab/newTab.xhtml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- 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 [
-  <!ENTITY % newTabDTD SYSTEM "chrome://browser/locale/newTab.dtd">
-  %newTabDTD;
-  <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
-  %browserDTD;
-  <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
-  %globalDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-  <title>&newtab.pageTitle;</title>
-
-  <link rel="stylesheet" type="text/css" media="all" href="chrome://global/skin/" />
-  <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/content/contentSearchUI.css" />
-  <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/content/newtab/newTab.css" />
-  <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/skin/newtab/newTab.css" />
-</head>
-
-<body dir="&locale.dir;">
-  <div id="newtab-customize-overlay"></div>
-
-  <div class="newtab-customize-panel-container">
-    <div id="newtab-customize-panel" orient="vertical">
-        <div id="newtab-customize-panel-anchor"></div>
-        <div id="newtab-customize-panel-inner-wrapper">
-          <div id="newtab-customize-title" class="newtab-customize-panel-item">
-            <label>&newtab.customize.cog.title2;</label>
-          </div>
-
-          <div class="newtab-customize-complex-option">
-            <div id="newtab-customize-classic" class="newtab-customize-panel-superitem newtab-customize-panel-item selectable">
-                <label>&newtab.customize.classic;</label>
-            </div>
-            <div id="newtab-customize-enhanced" class="newtab-customize-panel-subitem">
-                <label class="checkbox"></label>
-                <label>&newtab.customize.cog.enhanced;</label>
-            </div>
-          </div>
-          <div id="newtab-customize-blank" class="newtab-customize-panel-item selectable">
-            <label>&newtab.customize.blank2;</label>
-          </div>
-          <div id="newtab-customize-learn" class="newtab-customize-panel-item">
-            <label>&newtab.customize.cog.learn;</label>
-          </div>
-        </div>
-    </div>
-  </div>
-
-  <div id="newtab-vertical-margin">
-    <div id="newtab-margin-top"/>
-
-    <div id="newtab-margin-undo-container">
-      <div id="newtab-undo-container" undo-disabled="true">
-        <label id="newtab-undo-label">&newtab.undo.removedLabel;</label>
-        <button id="newtab-undo-button" tabindex="-1"
-                class="newtab-undo-button">&newtab.undo.undoButton;</button>
-        <button id="newtab-undo-restore-button" tabindex="-1"
-                class="newtab-undo-button">&newtab.undo.restoreButton;</button>
-        <button id="newtab-undo-close-button" tabindex="-1" title="&newtab.undo.closeTooltip;"/>
-      </div>
-    </div>
-
-    <div id="newtab-search-container">
-      <div id="newtab-search-form">
-        <div id="newtab-search-icon"/>
-        <input type="text" name="q" value="" id="newtab-search-text"
-               placeholder="&searchInput.placeholder;"
-               aria-label="&contentSearchInput.label;" maxlength="256"/>
-        <input id="newtab-search-submit" type="button"
-             title="&contentSearchSubmit.tooltip;"/>
-      </div>
-    </div>
-
-    <div id="newtab-horizontal-margin">
-      <div class="newtab-side-margin"/>
-      <div id="newtab-grid">
-        <h1 id="topsites-heading"/>
-      </div>
-      <div class="newtab-side-margin"/>
-    </div>
-
-    <div id="newtab-margin-bottom"/>
-  </div>
-  <input id="newtab-customize-button" type="button" dir="&locale.dir;"
-         value="&#x2699;"
-         title="&newtab.customize.title;"/>
-</body>
-<script type="text/javascript" src="chrome://browser/content/contentSearchUI.js"/>
-<script type="text/javascript" src="chrome://browser/content/newtab/newTab.js"/>
-</html>
deleted file mode 100644
--- a/browser/base/content/newtab/page.js
+++ /dev/null
@@ -1,248 +0,0 @@
-#ifdef 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/. */
-#endif
-
-// The amount of time we wait while coalescing updates for hidden pages.
-const SCHEDULE_UPDATE_TIMEOUT_MS = 1000;
-
-/**
- * This singleton represents the whole 'New Tab Page' and takes care of
- * initializing all its components.
- */
-var gPage = {
-  /**
-   * Initializes the page.
-   */
-  init: function Page_init() {
-    // Add ourselves to the list of pages to receive notifications.
-    gAllPages.register(this);
-
-    // Listen for 'unload' to unregister this page. Save a promise that can be
-    // passed to others to know when to clean up, e.g., background thumbnails.
-    this.unloadingPromise = new Promise(resolve => {
-      addEventListener("unload", () => {
-        resolve();
-        this._handleUnloadEvent();
-      });
-    });
-
-    // XXX bug 991111 - Not all click events are correctly triggered when
-    // listening from xhtml nodes -- in particular middle clicks on sites, so
-    // listen from the xul window and filter then delegate
-    addEventListener("click", this, false);
-
-    // Check if the new tab feature is enabled.
-    let enabled = gAllPages.enabled;
-    if (enabled)
-      this._init();
-
-    this._updateAttributes(enabled);
-
-    // Initialize customize controls.
-    gCustomize.init();
-  },
-
-  /**
-   * Listens for notifications specific to this page.
-   */
-  observe: function Page_observe(aSubject, aTopic, aData) {
-    if (aTopic == "nsPref:changed") {
-      gCustomize.updateSelected();
-
-      let enabled = gAllPages.enabled;
-      this._updateAttributes(enabled);
-
-      // Update thumbnails to the new enhanced setting
-      if (aData == "browser.newtabpage.enhanced") {
-        this.update();
-      }
-
-      // Initialize the whole page if we haven't done that, yet.
-      if (enabled) {
-        this._init();
-      } else {
-        gUndoDialog.hide();
-      }
-    } else if (aTopic == "page-thumbnail:create" && gGrid.ready) {
-      for (let site of gGrid.sites) {
-        if (site && site.url === aData) {
-          site.refreshThumbnail();
-        }
-      }
-    }
-  },
-
-  /**
-   * Updates the page's grid right away for visible pages. If the page is
-   * currently hidden, i.e. in a background tab or in the preloader, then we
-   * batch multiple update requests and refresh the grid once after a short
-   * delay. Accepts a single parameter the specifies the reason for requesting
-   * a page update. The page may decide to delay or prevent a requested updated
-   * based on the given reason.
-   */
-  update(reason = "") {
-    // Update immediately if we're visible.
-    if (!document.hidden) {
-      // Ignore updates where reason=links-changed as those signal that the
-      // provider's set of links changed. We don't want to update visible pages
-      // in that case, it is ok to wait until the user opens the next tab.
-      if (reason != "links-changed" && gGrid.ready) {
-        gGrid.refresh();
-      }
-
-      return;
-    }
-
-    // Bail out if we scheduled before.
-    if (this._scheduleUpdateTimeout) {
-      return;
-    }
-
-    this._scheduleUpdateTimeout = requestIdleCallback(() => {
-      // Refresh if the grid is ready.
-      if (gGrid.ready) {
-        gGrid.refresh();
-      }
-
-      this._scheduleUpdateTimeout = null;
-    }, {timeout: SCHEDULE_UPDATE_TIMEOUT_MS});
-  },
-
-  /**
-   * Internally initializes the page. This runs only when/if the feature
-   * is/gets enabled.
-   */
-  _init: function Page_init() {
-    if (this._initialized)
-      return;
-
-    this._initialized = true;
-
-    // Set submit button label for when CSS background are disabled (e.g.
-    // high contrast mode).
-    document.getElementById("newtab-search-submit").value =
-      document.body.getAttribute("dir") == "ltr" ? "\u25B6" : "\u25C0";
-
-    if (Services.prefs.getBoolPref("browser.newtabpage.compact")) {
-      document.body.classList.add("compact");
-    }
-
-    // Initialize search.
-    gSearch.init();
-
-    if (document.hidden) {
-      addEventListener("visibilitychange", this);
-    } else {
-      setTimeout(() => this.onPageFirstVisible());
-    }
-
-    // Initialize and render the grid.
-    gGrid.init();
-
-    // Initialize the drop target shim.
-    gDropTargetShim.init();
-
-#ifdef XP_MACOSX
-    // Workaround to prevent a delay on MacOSX due to a slow drop animation.
-    document.addEventListener("dragover", this);
-    document.addEventListener("drop", this);
-#endif
-  },
-
-  /**
-   * Updates the 'page-disabled' attributes of the respective DOM nodes.
-   * @param aValue Whether the New Tab Page is enabled or not.
-   */
-  _updateAttributes: function Page_updateAttributes(aValue) {
-    // Set the nodes' states.
-    let nodeSelector = "#newtab-grid, #newtab-search-container";
-    for (let node of document.querySelectorAll(nodeSelector)) {
-      if (aValue)
-        node.removeAttribute("page-disabled");
-      else
-        node.setAttribute("page-disabled", "true");
-    }
-
-    // Enables/disables the control and link elements.
-    let inputSelector = ".newtab-control, .newtab-link";
-    for (let input of document.querySelectorAll(inputSelector)) {
-      if (aValue)
-        input.removeAttribute("tabindex");
-      else
-        input.setAttribute("tabindex", "-1");
-    }
-  },
-
-  /**
-   * Handles unload event
-   */
-  _handleUnloadEvent: function Page_handleUnloadEvent() {
-    gAllPages.unregister(this);
-  },
-
-  /**
-   * Handles all page events.
-   */
-  handleEvent: function Page_handleEvent(aEvent) {
-    switch (aEvent.type) {
-      case "load":
-        this.onPageVisibleAndLoaded();
-        break;
-      case "click":
-        let {button, target} = aEvent;
-        // Go up ancestors until we find a Site or not
-        while (target) {
-          if (target.hasOwnProperty("_newtabSite")) {
-            target._newtabSite.onClick(aEvent);
-            break;
-          }
-          target = target.parentNode;
-        }
-        break;
-      case "dragover":
-        if (gDrag.isValid(aEvent) && gDrag.draggedSite)
-          aEvent.preventDefault();
-        break;
-      case "drop":
-        if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
-          aEvent.preventDefault();
-          aEvent.stopPropagation();
-        }
-        break;
-      case "visibilitychange":
-        // Cancel any delayed updates for hidden pages now that we're visible.
-        if (this._scheduleUpdateTimeout) {
-          cancelIdleCallback(this._scheduleUpdateTimeout);
-          this._scheduleUpdateTimeout = null;
-
-          // An update was pending so force an update now.
-          this.update();
-        }
-
-        setTimeout(() => this.onPageFirstVisible());
-        removeEventListener("visibilitychange", this);
-        break;
-    }
-  },
-
-  onPageFirstVisible: function () {
-    for (let site of gGrid.sites) {
-      if (site) {
-        site.captureIfMissing();
-      }
-    }
-
-    if (document.readyState == "complete") {
-      this.onPageVisibleAndLoaded();
-    } else {
-      addEventListener("load", this);
-    }
-  },
-
-  onPageVisibleAndLoaded() {
-    // Maybe tell the user they can undo an initial automigration
-    sendAsyncMessage("NewTab:MaybeShowMigrateMessage");
-  },
-};
deleted file mode 100644
--- a/browser/base/content/newtab/search.js
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifdef 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/. */
-#endif
-
-var gSearch = {
-  init: function () {
-    document.getElementById("newtab-search-submit")
-            .addEventListener("click", e => this._contentSearchController.search(e));
-    let textbox = document.getElementById("newtab-search-text");
-    this._contentSearchController =
-      new ContentSearchUIController(textbox, textbox.parentNode, "newtab", "newtab");
-  },
-};
deleted file mode 100644
--- a/browser/base/content/newtab/sites.js
+++ /dev/null
@@ -1,285 +0,0 @@
-#ifdef 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/. */
-#endif
-
-const THUMBNAIL_PLACEHOLDER_ENABLED =
-  Services.prefs.getBoolPref("browser.newtabpage.thumbnailPlaceholder");
-
-/**
- * This class represents a site that is contained in a cell and can be pinned,
- * moved around or deleted.
- */
-function Site(aNode, aLink) {
-  this._node = aNode;
-  this._node._newtabSite = this;
-
-  this._link = aLink;
-
-  this._render();
-  this._addEventHandlers();
-}
-
-Site.prototype = {
-  /**
-   * The site's DOM node.
-   */
-  get node() { return this._node; },
-
-  /**
-   * The site's link.
-   */
-  get link() { return this._link; },
-
-  /**
-   * The url of the site's link.
-   */
-  get url() { return this.link.url; },
-
-  /**
-   * The title of the site's link.
-   */
-  get title() { return this.link.title || this.link.url; },
-
-  /**
-   * The site's parent cell.
-   */
-  get cell() {
-    let parentNode = this.node.parentNode;
-    return parentNode && parentNode._newtabCell;
-  },
-
-  /**
-   * Pins the site on its current or a given index.
-   * @param aIndex The pinned index (optional).
-   */
-  pin: function Site_pin(aIndex) {
-    if (typeof aIndex == "undefined")
-      aIndex = this.cell.index;
-
-    this._updateAttributes(true);
-    gPinnedLinks.pin(this._link, aIndex);
-  },
-
-  /**
-   * Unpins the site and calls the given callback when done.
-   */
-  unpin: function Site_unpin() {
-    if (this.isPinned()) {
-      this._updateAttributes(false);
-      gPinnedLinks.unpin(this._link);
-      gUpdater.updateGrid();
-    }
-  },
-
-  /**
-   * Checks whether this site is pinned.
-   * @return Whether this site is pinned.
-   */
-  isPinned: function Site_isPinned() {
-    return gPinnedLinks.isPinned(this._link);
-  },
-
-  /**
-   * Blocks the site (removes it from the grid) and calls the given callback
-   * when done.
-   */
-  block: function Site_block() {
-    if (!gBlockedLinks.isBlocked(this._link)) {
-      gUndoDialog.show(this);
-      gBlockedLinks.block(this._link);
-      gUpdater.updateGrid();
-    }
-  },
-
-  /**
-   * Gets the DOM node specified by the given query selector.
-   * @param aSelector The query selector.
-   * @return The DOM node we found.
-   */
-  _querySelector: function Site_querySelector(aSelector) {
-    return this.node.querySelector(aSelector);
-  },
-
-  /**
-   * Updates attributes for all nodes which status depends on this site being
-   * pinned or unpinned.
-   * @param aPinned Whether this site is now pinned or unpinned.
-   */
-  _updateAttributes: function (aPinned) {
-    let control = this._querySelector(".newtab-control-pin");
-
-    if (aPinned) {
-      this.node.setAttribute("pinned", true);
-      control.setAttribute("title", newTabString("unpin"));
-    } else {
-      this.node.removeAttribute("pinned");
-      control.setAttribute("title", newTabString("pin"));
-    }
-  },
-
-  _newTabString: function(str, substrArr) {
-    let regExp = /%[0-9]\$S/g;
-    let matches;
-    while ((matches = regExp.exec(str))) {
-      let match = matches[0];
-      let index = match.charAt(1); // Get the digit in the regExp.
-      str = str.replace(match, substrArr[index - 1]);
-    }
-    return str;
-  },
-
-  /**
-   * Renders the site's data (fills the HTML fragment).
-   */
-  _render: function Site_render() {
-    // setup display variables
-    let enhanced = gAllPages.enhanced;
-    let url = this.url;
-    let title = enhanced && enhanced.title ? enhanced.title :
-                this.link.type == "history" ? this.link.baseDomain :
-                this.title;
-    let tooltip = (this.title == url ? this.title : this.title + "\n" + url);
-
-    let link = this._querySelector(".newtab-link");
-    link.setAttribute("title", tooltip);
-    link.setAttribute("href", url);
-    this.node.setAttribute("type", this.link.type);
-
-    let titleNode = this._querySelector(".newtab-title");
-    titleNode.textContent = title;
-    if (this.link.titleBgColor) {
-      titleNode.style.backgroundColor = this.link.titleBgColor;
-    }
-
-    if (this.isPinned())
-      this._updateAttributes(true);
-    // Capture the page if the thumbnail is missing, which will cause page.js
-    // to be notified and call our refreshThumbnail() method.
-    this.captureIfMissing();
-    // but still display whatever thumbnail might be available now.
-    this.refreshThumbnail();
-  },
-
-  /**
-   * Captures the site's thumbnail in the background, but only if there's no
-   * existing thumbnail and the page allows background captures.
-   */
-  captureIfMissing: function Site_captureIfMissing() {
-    if (!document.hidden && !this.link.imageURI) {
-      const {unloadingPromise} = gPage;
-      BackgroundPageThumbs.captureIfMissing(this.url, {unloadingPromise});
-    }
-  },
-
-  /**
-   * Refreshes the thumbnail for the site.
-   */
-  refreshThumbnail: function Site_refreshThumbnail() {
-    // Only enhance tiles if that feature is turned on
-    let link = gAllPages.enhanced || this.link;
-
-    let thumbnail = this._querySelector(".newtab-thumbnail.thumbnail");
-    if (link.bgColor) {
-      thumbnail.style.backgroundColor = link.bgColor;
-    }
-    let uri = link.imageURI || PageThumbs.getThumbnailURL(this.url);
-    thumbnail.src = uri;
-
-    if (THUMBNAIL_PLACEHOLDER_ENABLED &&
-        link.type == "history" &&
-        link.baseDomain) {
-      let placeholder = this._querySelector(".newtab-thumbnail.placeholder");
-      let charCodeSum = 0;
-      for (let c of link.baseDomain) {
-        charCodeSum += c.charCodeAt(0);
-      }
-      const COLORS = 16;
-      let hue = Math.round((charCodeSum % COLORS) / COLORS * 360);
-      placeholder.style.backgroundColor = "hsl(" + hue + ",80%,40%)";
-      placeholder.textContent = link.baseDomain.substr(0,1).toUpperCase();
-    }
-
-    if (link.enhancedImageURI) {
-      let enhanced = this._querySelector(".enhanced-content");
-      enhanced.src = link.enhancedImageURI;
-    }
-  },
-
-  /**
-   * Adds event handlers for the site and its buttons.
-   */
-  _addEventHandlers: function Site_addEventHandlers() {
-    // Register drag-and-drop event handlers.
-    this._node.addEventListener("dragstart", this);
-    this._node.addEventListener("dragend", this);
-    this._node.addEventListener("mouseover", this);
-  },
-
-  /**
-   * Speculatively opens a connection to the current site.
-   */
-  _speculativeConnect: function Site_speculativeConnect() {
-    let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect);
-    let uri = Services.io.newURI(this.url);
-
-    if (!uri.schemeIs("http") && !uri.schemeIs("https")) {
-      return;
-    }
-
-    try {
-      // This can throw for certain internal URLs, when they wind up in
-      // about:newtab. Be sure not to propagate the error.
-
-      // We use the URI's codebase principal here to open its speculative
-      // connection.
-      let originAttributes = document.docShell.getOriginAttributes();
-      let principal = Services.scriptSecurityManager
-                              .createCodebasePrincipal(uri, originAttributes);
-      sc.speculativeConnect2(uri, principal, null);
-    } catch (e) {}
-  },
-
-  /**
-   * Handles site click events.
-   */
-  onClick: function Site_onClick(aEvent) {
-    let pinned = this.isPinned();
-    let {button, target} = aEvent;
-    const isLinkClick = target.classList.contains("newtab-link") ||
-      target.parentElement.classList.contains("newtab-link");
-
-    // Handle primary click for pin and block
-    if (button == 0 && !isLinkClick) {
-      aEvent.preventDefault();
-      if (target.classList.contains("newtab-control-block")) {
-        this.block();
-      }
-      else if (pinned && target.classList.contains("newtab-control-pin")) {
-        this.unpin();
-      }
-      else if (!pinned && target.classList.contains("newtab-control-pin")) {
-        this.pin();
-      }
-    }
-  },
-
-  /**
-   * Handles all site events.
-   */
-  handleEvent: function Site_handleEvent(aEvent) {
-    switch (aEvent.type) {
-      case "mouseover":
-        this._node.removeEventListener("mouseover", this);
-        this._speculativeConnect();
-        break;
-      case "dragstart":
-        gDrag.start(this, aEvent);
-        break;
-      case "dragend":
-        gDrag.end(this, aEvent);
-        break;
-    }
-  }
-};
deleted file mode 100644
--- a/browser/base/content/newtab/transformations.js
+++ /dev/null
@@ -1,270 +0,0 @@
-#ifdef 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/. */
-#endif
-
-/**
- * This singleton allows to transform the grid by repositioning a site's node
- * in the DOM and by showing or hiding the node. It additionally provides
- * convenience methods to work with a site's DOM node.
- */
-var gTransformation = {
-  /**
-   * Returns the width of the left and top border of a cell. We need to take it
-   * into account when measuring and comparing site and cell positions.
-   */
-  get _cellBorderWidths() {
-    let cstyle = window.getComputedStyle(gGrid.cells[0].node);
-    let widths = {
-      left: parseInt(cstyle.getPropertyValue("border-left-width")),
-      top: parseInt(cstyle.getPropertyValue("border-top-width"))
-    };
-
-    // Cache this value, overwrite the getter.
-    Object.defineProperty(this, "_cellBorderWidths",
-                          {value: widths, enumerable: true});
-
-    return widths;
-  },
-
-  /**
-   * Gets a DOM node's position.
-   * @param aNode The DOM node.
-   * @return A Rect instance with the position.
-   */
-  getNodePosition: function Transformation_getNodePosition(aNode) {
-    let {left, top, width, height} = aNode.getBoundingClientRect();
-    return new Rect(left + scrollX, top + scrollY, width, height);
-  },
-
-  /**
-   * Fades a given node from zero to full opacity.
-   * @param aNode The node to fade.
-   * @param aCallback The callback to call when finished.
-   */
-  fadeNodeIn: function Transformation_fadeNodeIn(aNode, aCallback) {
-    this._setNodeOpacity(aNode, 1, function () {
-      // Clear the style property.
-      aNode.style.opacity = "";
-
-      if (aCallback)
-        aCallback();
-    });
-  },
-
-  /**
-   * Fades a given node from full to zero opacity.
-   * @param aNode The node to fade.
-   * @param aCallback The callback to call when finished.
-   */
-  fadeNodeOut: function Transformation_fadeNodeOut(aNode, aCallback) {
-    this._setNodeOpacity(aNode, 0, aCallback);
-  },
-
-  /**
-   * Fades a given site from zero to full opacity.
-   * @param aSite The site to fade.
-   * @param aCallback The callback to call when finished.
-   */
-  showSite: function Transformation_showSite(aSite, aCallback) {
-    this.fadeNodeIn(aSite.node, aCallback);
-  },
-
-  /**
-   * Fades a given site from full to zero opacity.
-   * @param aSite The site to fade.
-   * @param aCallback The callback to call when finished.
-   */
-  hideSite: function Transformation_hideSite(aSite, aCallback) {
-    this.fadeNodeOut(aSite.node, aCallback);
-  },
-
-  /**
-   * Allows to set a site's position.
-   * @param aSite The site to re-position.
-   * @param aPosition The desired position for the given site.
-   */
-  setSitePosition: function Transformation_setSitePosition(aSite, aPosition) {
-    let style = aSite.node.style;
-    let {top, left} = aPosition;
-
-    style.top = top + "px";
-    style.left = left + "px";
-  },
-
-  /**
-   * Freezes a site in its current position by positioning it absolute.
-   * @param aSite The site to freeze.
-   */
-  freezeSitePosition: function Transformation_freezeSitePosition(aSite) {
-    if (this._isFrozen(aSite))
-      return;
-
-    let style = aSite.node.style;
-    let comp = getComputedStyle(aSite.node, null);
-    style.width = comp.getPropertyValue("width");
-    style.height = comp.getPropertyValue("height");
-
-    aSite.node.setAttribute("frozen", "true");
-    this.setSitePosition(aSite, this.getNodePosition(aSite.node));
-  },
-
-  /**
-   * Unfreezes a site by removing its absolute positioning.
-   * @param aSite The site to unfreeze.
-   */
-  unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) {
-    if (!this._isFrozen(aSite))
-      return;
-
-    let style = aSite.node.style;
-    style.left = style.top = style.width = style.height = "";
-    aSite.node.removeAttribute("frozen");
-  },
-
-  /**
-   * Slides the given site to the target node's position.
-   * @param aSite The site to move.
-   * @param aTarget The slide target.
-   * @param aOptions Set of options (see below).
-   *        unfreeze - unfreeze the site after sliding
-   *        callback - the callback to call when finished
-   */
-  slideSiteTo: function Transformation_slideSiteTo(aSite, aTarget, aOptions) {
-    let currentPosition = this.getNodePosition(aSite.node);
-    let targetPosition = this.getNodePosition(aTarget.node)
-    let callback = aOptions && aOptions.callback;
-
-    let self = this;
-
-    function finish() {
-      if (aOptions && aOptions.unfreeze)
-        self.unfreezeSitePosition(aSite);
-
-      if (callback)
-        callback();
-    }
-
-    // We need to take the width of a cell's border into account.
-    targetPosition.left += this._cellBorderWidths.left;
-    targetPosition.top += this._cellBorderWidths.top;
-
-    // Nothing to do here if the positions already match.
-    if (currentPosition.left == targetPosition.left &&
-        currentPosition.top == targetPosition.top) {
-      finish();
-    } else {
-      this.setSitePosition(aSite, targetPosition);
-      this._whenTransitionEnded(aSite.node, ["left", "top"], finish);
-    }
-  },
-
-  /**
-   * Rearranges a given array of sites and moves them to their new positions or
-   * fades in/out new/removed sites.
-   * @param aSites An array of sites to rearrange.
-   * @param aOptions Set of options (see below).
-   *        unfreeze - unfreeze the site after rearranging
-   *        callback - the callback to call when finished
-   */
-  rearrangeSites: function Transformation_rearrangeSites(aSites, aOptions) {
-    let batch = [];
-    let cells = gGrid.cells;
-    let callback = aOptions && aOptions.callback;
-    let unfreeze = aOptions && aOptions.unfreeze;
-
-    aSites.forEach(function (aSite, aIndex) {
-      // Do not re-arrange empty cells or the dragged site.
-      if (!aSite || aSite == gDrag.draggedSite)
-        return;
-
-      batch.push(new Promise(resolve => {
-        if (!cells[aIndex]) {
-          // The site disappeared from the grid, hide it.
-          this.hideSite(aSite, resolve);
-        } else if (this._getNodeOpacity(aSite.node) != 1) {
-          // The site disappeared before but is now back, show it.
-          this.showSite(aSite, resolve);
-        } else {
-          // The site's position has changed, move it around.
-          this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: resolve});
-        }
-      }));
-    }, this);
-
-    if (callback) {
-      Promise.all(batch).then(callback);
-    }
-  },
-
-  /**
-   * Listens for the 'transitionend' event on a given node and calls the given
-   * callback.
-   * @param aNode The node that is transitioned.
-   * @param aProperties The properties we'll wait to be transitioned.
-   * @param aCallback The callback to call when finished.
-   */
-  _whenTransitionEnded:
-    function Transformation_whenTransitionEnded(aNode, aProperties, aCallback) {
-
-    let props = new Set(aProperties);
-    aNode.addEventListener("transitionend", function onEnd(e) {
-      if (props.has(e.propertyName)) {
-        aNode.removeEventListener("transitionend", onEnd);
-        aCallback();
-      }
-    });
-  },
-
-  /**
-   * Gets a given node's opacity value.
-   * @param aNode The node to get the opacity value from.
-   * @return The node's opacity value.
-   */
-  _getNodeOpacity: function Transformation_getNodeOpacity(aNode) {
-    let cstyle = window.getComputedStyle(aNode);
-    return cstyle.getPropertyValue("opacity");
-  },
-
-  /**
-   * Sets a given node's opacity.
-   * @param aNode The node to set the opacity value for.
-   * @param aOpacity The opacity value to set.
-   * @param aCallback The callback to call when finished.
-   */
-  _setNodeOpacity:
-    function Transformation_setNodeOpacity(aNode, aOpacity, aCallback) {
-
-    if (this._getNodeOpacity(aNode) == aOpacity) {
-      if (aCallback)
-        aCallback();
-    } else {
-      if (aCallback) {
-        this._whenTransitionEnded(aNode, ["opacity"], aCallback);
-      }
-
-      aNode.style.opacity = aOpacity;
-    }
-  },
-
-  /**
-   * Moves a site to the cell with the given index.
-   * @param aSite The site to move.
-   * @param aIndex The target cell's index.
-   * @param aOptions Options that are directly passed to slideSiteTo().
-   */
-  _moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) {
-    this.freezeSitePosition(aSite);
-    this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions);
-  },
-
-  /**
-   * Checks whether a site is currently frozen.
-   * @param aSite The site to check.
-   * @return Whether the given site is frozen.
-   */
-  _isFrozen: function Transformation_isFrozen(aSite) {
-    return aSite.node.hasAttribute("frozen");
-  }
-};
deleted file mode 100644
--- a/browser/base/content/newtab/undo.js
+++ /dev/null
@@ -1,116 +0,0 @@
-#ifdef 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/. */
-#endif
-
-/**
- * Dialog allowing to undo the removal of single site or to completely restore
- * the grid's original state.
- */
-var gUndoDialog = {
-  /**
-   * The undo dialog's timeout in miliseconds.
-   */
-  HIDE_TIMEOUT_MS: 15000,
-
-  /**
-   * Contains undo information.
-   */
-  _undoData: null,
-
-  /**
-   * Initializes the undo dialog.
-   */
-  init: function UndoDialog_init() {
-    this._undoContainer = document.getElementById("newtab-undo-container");
-    this._undoContainer.addEventListener("click", this);
-    this._undoButton = document.getElementById("newtab-undo-button");
-    this._undoCloseButton = document.getElementById("newtab-undo-close-button");
-    this._undoRestoreButton = document.getElementById("newtab-undo-restore-button");
-  },
-
-  /**
-   * Shows the undo dialog.
-   * @param aSite The site that just got removed.
-   */
-  show: function UndoDialog_show(aSite) {
-    if (this._undoData)
-      clearTimeout(this._undoData.timeout);
-
-    this._undoData = {
-      index: aSite.cell.index,
-      wasPinned: aSite.isPinned(),
-      blockedLink: aSite.link,
-      timeout: setTimeout(this.hide.bind(this), this.HIDE_TIMEOUT_MS)
-    };
-
-    this._undoContainer.removeAttribute("undo-disabled");
-    this._undoButton.removeAttribute("tabindex");
-    this._undoCloseButton.removeAttribute("tabindex");
-    this._undoRestoreButton.removeAttribute("tabindex");
-  },
-
-  /**
-   * Hides the undo dialog.
-   */
-  hide: function UndoDialog_hide() {
-    if (!this._undoData)
-      return;
-
-    clearTimeout(this._undoData.timeout);
-    this._undoData = null;
-    this._undoContainer.setAttribute("undo-disabled", "true");
-    this._undoButton.setAttribute("tabindex", "-1");
-    this._undoCloseButton.setAttribute("tabindex", "-1");
-    this._undoRestoreButton.setAttribute("tabindex", "-1");
-  },
-
-  /**
-   * The undo dialog event handler.
-   * @param aEvent The event to handle.
-   */
-  handleEvent: function UndoDialog_handleEvent(aEvent) {
-    switch (aEvent.target.id) {
-      case "newtab-undo-button":
-        this._undo();
-        break;
-      case "newtab-undo-restore-button":
-        this._undoAll();
-        break;
-      case "newtab-undo-close-button":
-        this.hide();
-        break;
-    }
-  },
-
-  /**
-   * Undo the last blocked site.
-   */
-  _undo: function UndoDialog_undo() {
-    if (!this._undoData)
-      return;
-
-    let {index, wasPinned, blockedLink} = this._undoData;
-    gBlockedLinks.unblock(blockedLink);
-
-    if (wasPinned) {
-      gPinnedLinks.pin(blockedLink, index);
-    }
-
-    gUpdater.updateGrid();
-    this.hide();
-  },
-
-  /**
-   * Undo all blocked sites.
-   */
-  _undoAll: function UndoDialog_undoAll() {
-    NewTabUtils.undoAll(() => {
-      gUpdater.updateGrid();
-      this.hide();
-    });
-  }
-};
-
-gUndoDialog.init();
deleted file mode 100644
--- a/browser/base/content/newtab/updater.js
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifdef 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/. */
-#endif
-
-/**
- * This singleton provides functionality to update the current grid to a new
- * set of pinned and blocked sites. It adds, moves and removes sites.
- */
-var gUpdater = {
-  /**
-   * Updates the current grid according to its pinned and blocked sites.
-   * This removes old, moves existing and creates new sites to fill gaps.
-   * @param aCallback The callback to call when finished.
-   */
-  updateGrid: function Updater_updateGrid(aCallback) {
-    let links = gLinks.getLinks().slice(0, gGrid.cells.length);
-
-    // Find all sites that remain in the grid.
-    let sites = this._findRemainingSites(links);
-
-    // Remove sites that are no longer in the grid.
-    this._removeLegacySites(sites, () => {
-      // Freeze all site positions so that we can move their DOM nodes around
-      // without any visual impact.
-      this._freezeSitePositions(sites);
-
-      // Move the sites' DOM nodes to their new position in the DOM. This will
-      // have no visual effect as all the sites have been frozen and will
-      // remain in their current position.
-      this._moveSiteNodes(sites);
-
-      // Now it's time to animate the sites actually moving to their new
-      // positions.
-      this._rearrangeSites(sites, () => {
-        // Try to fill empty cells and finish.
-        this._fillEmptyCells(links, aCallback);
-
-        // Update other pages that might be open to keep them synced.
-        gAllPages.update(gPage);
-      });
-    });
-  },
-
-  /**
-   * Takes an array of links and tries to correlate them to sites contained in
-   * the current grid. If no corresponding site can be found (i.e. the link is
-   * new and a site will be created) then just set it to null.
-   * @param aLinks The array of links to find sites for.
-   * @return Array of sites mapped to the given links (can contain null values).
-   */
-  _findRemainingSites: function Updater_findRemainingSites(aLinks) {
-    let map = {};
-
-    // Create a map to easily retrieve the site for a given URL.
-    gGrid.sites.forEach(function (aSite) {
-      if (aSite)
-        map[aSite.url] = aSite;
-    });
-
-    // Map each link to its corresponding site, if any.
-    return aLinks.map(function (aLink) {
-      return aLink && (aLink.url in map) && map[aLink.url];
-    });
-  },
-
-  /**
-   * Freezes the given sites' positions.
-   * @param aSites The array of sites to freeze.
-   */
-  _freezeSitePositions: function Updater_freezeSitePositions(aSites) {
-    aSites.forEach(function (aSite) {
-      if (aSite)
-        gTransformation.freezeSitePosition(aSite);
-    });
-  },
-
-  /**
-   * Moves the given sites' DOM nodes to their new positions.
-   * @param aSites The array of sites to move.
-   */
-  _moveSiteNodes: function Updater_moveSiteNodes(aSites) {
-    let cells = gGrid.cells;
-
-    // Truncate the given array of sites to not have more sites than cells.
-    // This can happen when the user drags a bookmark (or any other new kind
-    // of link) onto the grid.
-    let sites = aSites.slice(0, cells.length);
-
-    sites.forEach(function (aSite, aIndex) {
-      let cell = cells[aIndex];
-      let cellSite = cell.site;
-
-      // The site's position didn't change.
-      if (!aSite || cellSite != aSite) {
-        let cellNode = cell.node;
-
-        // Empty the cell if necessary.
-        if (cellSite)
-          cellNode.removeChild(cellSite.node);
-
-        // Put the new site in place, if any.
-        if (aSite)
-          cellNode.appendChild(aSite.node);
-      }
-    }, this);
-  },
-
-  /**
-   * Rearranges the given sites and slides them to their new positions.
-   * @param aSites The array of sites to re-arrange.
-   * @param aCallback The callback to call when finished.
-   */
-  _rearrangeSites: function Updater_rearrangeSites(aSites, aCallback) {
-    let options = {callback: aCallback, unfreeze: true};
-    gTransformation.rearrangeSites(aSites, options);
-  },
-
-  /**
-   * Removes all sites from the grid that are not in the given links array or
-   * exceed the grid.
-   * @param aSites The array of sites remaining in the grid.
-   * @param aCallback The callback to call when finished.
-   */
-  _removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) {
-    let batch = [];
-
-    // Delete sites that were removed from the grid.
-    gGrid.sites.forEach(function (aSite) {
-      // The site must be valid and not in the current grid.
-      if (!aSite || aSites.includes(aSite))
-        return;
-
-      batch.push(new Promise(resolve => {
-        // Fade out the to-be-removed site.
-        gTransformation.hideSite(aSite, function () {
-          let node = aSite.node;
-
-          // Remove the site from the DOM.
-          node.remove();
-          resolve();
-        });
-      }));
-    });
-
-    Promise.all(batch).then(aCallback);
-  },
-
-  /**
-   * Tries to fill empty cells with new links if available.
-   * @param aLinks The array of links.
-   * @param aCallback The callback to call when finished.
-   */
-  _fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
-    let {cells, sites} = gGrid;
-
-    // Find empty cells and fill them.
-    Promise.all(sites.map((aSite, aIndex) => {
-      if (aSite || !aLinks[aIndex])
-        return null;
-
-      return new Promise(resolve => {
-        // Create the new site and fade it in.
-        let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
-
-        // Set the site's initial opacity to zero.
-        site.node.style.opacity = 0;
-
-        // Flush all style changes for the dynamically inserted site to make
-        // the fade-in transition work.
-        window.getComputedStyle(site.node).opacity;
-        gTransformation.showSite(site, resolve);
-      });
-    })).then(aCallback).catch(console.exception);
-  }
-};
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -1,17 +1,17 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* eslint-env mozilla/browser-window */
 
-class TabBrowser {
-  constructor() {
+window._gBrowser = {
+  init() {
     this.requiresAddonInterpositions = true;
 
     ChromeUtils.defineModuleGetter(this, "AsyncTabSwitcher",
       "resource:///modules/AsyncTabSwitcher.jsm");
 
     XPCOMUtils.defineLazyServiceGetters(this, {
       _unifiedComplete: ["@mozilla.org/autocomplete/search;1?name=unifiedcomplete", "mozIPlacesAutoComplete"],
       serializationHelper: ["@mozilla.org/network/serialization-helper;1", "nsISerializationHelper"],
@@ -23,22 +23,22 @@ class TabBrowser {
 
     this.mPanelContainer = document.getElementById("tabbrowser-tabpanels");
     this.addEventListener = this.mPanelContainer.addEventListener.bind(this.mPanelContainer);
     this.removeEventListener = this.mPanelContainer.removeEventListener.bind(this.mPanelContainer);
     this.dispatchEvent = this.mPanelContainer.dispatchEvent.bind(this.mPanelContainer);
 
     this.initialBrowser = document.getElementById("tabbrowser-initialBrowser");
 
+    this.tabbox = document.getElementById("tabbrowser-tabbox");
+
     this.tabContainer = document.getElementById("tabbrowser-tabs");
 
     this.tabs = this.tabContainer.childNodes;
 
-    this.tabbox = document.getElementById("tabbrowser-tabbox");
-
     this.closingTabsEnum = { ALL: 0, OTHER: 1, TO_END: 2 };
 
     this._visibleTabs = null;
 
     this.mCurrentTab = null;
 
     this._lastRelatedTabMap = new WeakMap();
 
@@ -151,19 +151,16 @@ class TabBrowser {
 
     this._soundPlayingAttrRemovalTimer = 0;
 
     this._hoverTabTimer = null;
 
     this.mCurrentBrowser = this.initialBrowser;
     this.mCurrentBrowser.permanentKey = {};
 
-    CustomizableUI.addListener(this);
-    this._updateNewTabVisibility();
-
     Services.obs.addObserver(this, "contextual-identity-updated");
 
     this.mCurrentTab = this.tabContainer.firstChild;
     const nsIEventListenerService =
       Ci.nsIEventListenerService;
     let els = Cc["@mozilla.org/eventlistenerservice;1"]
       .getService(nsIEventListenerService);
     els.addSystemEventListener(document, "keydown", this, false);
@@ -249,231 +246,231 @@ class TabBrowser {
       "browser.tabs.tabMinWidth", this._tabMinWidthLimit,
       (pref, prevValue, newValue) => this.tabMinWidth = newValue,
       newValue => Math.max(newValue, this._tabMinWidthLimit),
     );
 
     this.tabMinWidth = this.tabMinWidthPref;
 
     this._setupEventListeners();
-  }
+  },
 
   get tabContextMenu() {
     return this.tabContainer.contextMenu;
-  }
+  },
 
   get visibleTabs() {
     if (!this._visibleTabs)
       this._visibleTabs = Array.filter(this.tabs,
         tab => !tab.hidden && !tab.closing);
     return this._visibleTabs;
-  }
+  },
 
   get _numPinnedTabs() {
     for (var i = 0; i < this.tabs.length; i++) {
       if (!this.tabs[i].pinned)
         break;
     }
     return i;
-  }
+  },
 
   get popupAnchor() {
     if (this.mCurrentTab._popupAnchor) {
       return this.mCurrentTab._popupAnchor;
     }
     let stack = this.mCurrentBrowser.parentNode;
     // Create an anchor for the popup
     let popupAnchor = document.createElementNS(this._XUL_NS, "hbox");
     popupAnchor.className = "popup-anchor";
     popupAnchor.hidden = true;
     stack.appendChild(popupAnchor);
     return this.mCurrentTab._popupAnchor = popupAnchor;
-  }
+  },
 
   set selectedTab(val) {
     if (gNavToolbox.collapsed && !this._allowTabChange) {
       return this.tabbox.selectedTab;
     }
     // Update the tab
     this.tabbox.selectedTab = val;
     return val;
-  }
+  },
 
   get selectedTab() {
     return this.mCurrentTab;
-  }
+  },
 
   get selectedBrowser() {
     return this.mCurrentBrowser;
-  }
+  },
 
   /**
    * BEGIN FORWARDED BROWSER PROPERTIES.  IF YOU ADD A PROPERTY TO THE BROWSER ELEMENT
    * MAKE SURE TO ADD IT HERE AS WELL.
    */
   get canGoBack() {
     return this.mCurrentBrowser.canGoBack;
-  }
+  },
 
   get canGoForward() {
     return this.mCurrentBrowser.canGoForward;
-  }
+  },
 
   goBack() {
     return this.mCurrentBrowser.goBack();
-  }
+  },
 
   goForward() {
     return this.mCurrentBrowser.goForward();
-  }
+  },
 
   reload() {
     return this.mCurrentBrowser.reload();
-  }
+  },
 
   reloadWithFlags(aFlags) {
     return this.mCurrentBrowser.reloadWithFlags(aFlags);
-  }
+  },
 
   stop() {
     return this.mCurrentBrowser.stop();
-  }
+  },
 
   /**
    * throws exception for unknown schemes
    */
   loadURI(aURI, aReferrerURI, aCharset) {
     return this.mCurrentBrowser.loadURI(aURI, aReferrerURI, aCharset);
-  }
+  },
 
   /**
    * throws exception for unknown schemes
    */
   loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData) {
     // Note - the callee understands both:
     // (a) loadURIWithFlags(aURI, aFlags, ...)
     // (b) loadURIWithFlags(aURI, { flags: aFlags, ... })
     // Forwarding it as (a) here actually supports both (a) and (b),
     // so you can call us either way too.
     return this.mCurrentBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData);
-  }
+  },
 
   goHome() {
     return this.mCurrentBrowser.goHome();
-  }
+  },
 
   gotoIndex(aIndex) {
     return this.mCurrentBrowser.gotoIndex(aIndex);
-  }
+  },
 
   set homePage(val) {
     this.mCurrentBrowser.homePage = val;
     return val;
-  }
+  },
 
   get homePage() {
     return this.mCurrentBrowser.homePage;
-  }
+  },
 
   get currentURI() {
     return this.mCurrentBrowser.currentURI;
-  }
+  },
 
   get finder() {
     return this.mCurrentBrowser.finder;
-  }
+  },
 
   get docShell() {
     return this.mCurrentBrowser.docShell;
-  }
+  },
 
   get webNavigation() {
     return this.mCurrentBrowser.webNavigation;
-  }
+  },
 
   get webBrowserFind() {
     return this.mCurrentBrowser.webBrowserFind;
-  }
+  },
 
   get webProgress() {
     return this.mCurrentBrowser.webProgress;
-  }
+  },
 
   get contentWindow() {
     return this.mCurrentBrowser.contentWindow;
-  }
+  },
 
   get contentWindowAsCPOW() {
     return this.mCurrentBrowser.contentWindowAsCPOW;
-  }
+  },
 
   get sessionHistory() {
     return this.mCurrentBrowser.sessionHistory;
-  }
+  },
 
   get markupDocumentViewer() {
     return this.mCurrentBrowser.markupDocumentViewer;
-  }
+  },
 
   get contentDocument() {
     return this.mCurrentBrowser.contentDocument;
-  }
+  },
 
   get contentDocumentAsCPOW() {
     return this.mCurrentBrowser.contentDocumentAsCPOW;
-  }
+  },
 
   get contentTitle() {
     return this.mCurrentBrowser.contentTitle;
-  }
+  },
 
   get contentPrincipal() {
     return this.mCurrentBrowser.contentPrincipal;
-  }
+  },
 
   get securityUI() {
     return this.mCurrentBrowser.securityUI;
-  }
+  },
 
   set fullZoom(val) {
     this.mCurrentBrowser.fullZoom = val;
-  }
+  },
 
   get fullZoom() {
     return this.mCurrentBrowser.fullZoom;
-  }
+  },
 
   set textZoom(val) {
     this.mCurrentBrowser.textZoom = val;
-  }
+  },
 
   get textZoom() {
     return this.mCurrentBrowser.textZoom;
-  }
+  },
 
   get isSyntheticDocument() {
     return this.mCurrentBrowser.isSyntheticDocument;
-  }
+  },
 
   set userTypedValue(val) {
     return this.mCurrentBrowser.userTypedValue = val;
-  }
+  },
 
   get userTypedValue() {
     return this.mCurrentBrowser.userTypedValue;
-  }
+  },
 
   set tabMinWidth(val) {
     this.tabContainer.style.setProperty("--tab-min-width", val + "px");
     return val;
-  }
+  },
 
   isFindBarInitialized(aTab) {
     return (aTab || this.selectedTab)._findBar != undefined;
-  }
+  },
 
   getFindBar(aTab) {
     if (!aTab)
       aTab = this.selectedTab;
 
     if (aTab._findBar)
       return aTab._findBar;
 
@@ -490,35 +487,35 @@ class TabBrowser {
 
     aTab._findBar = findBar;
 
     let event = document.createEvent("Events");
     event.initEvent("TabFindInitialized", true, false);
     aTab.dispatchEvent(event);
 
     return findBar;
-  }
+  },
 
   getStatusPanel() {
     if (!this._statusPanel) {
       this._statusPanel = document.createElementNS(this._XUL_NS, "statuspanel");
       this._statusPanel.setAttribute("inactive", "true");
       this._statusPanel.setAttribute("layer", "true");
       this._appendStatusPanel();
     }
     return this._statusPanel;
-  }
+  },
 
   _appendStatusPanel() {
     if (this._statusPanel) {
       let browser = this.selectedBrowser;
       let browserContainer = this.getBrowserContainer(browser);
       browserContainer.insertBefore(this._statusPanel, browser.parentNode.nextSibling);
     }
-  }
+  },
 
   pinTab(aTab) {
     if (aTab.pinned)
       return;
 
     if (aTab.hidden)
       this.showTab(aTab);
 
@@ -528,17 +525,17 @@ class TabBrowser {
     this.tabContainer._positionPinnedTabs();
     this.tabContainer._updateCloseButtons();
 
     this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: true });
 
     let event = document.createEvent("Events");
     event.initEvent("TabPinned", true, false);
     aTab.dispatchEvent(event);
-  }
+  },
 
   unpinTab(aTab) {
     if (!aTab.pinned)
       return;
 
     this.moveTabTo(aTab, this._numPinnedTabs - 1);
     aTab.removeAttribute("pinned");
     aTab.style.marginInlineStart = "";
@@ -546,30 +543,30 @@ class TabBrowser {
     this.tabContainer._positionPinnedTabs();
     this.tabContainer._updateCloseButtons();
 
     this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: false });
 
     let event = document.createEvent("Events");
     event.initEvent("TabUnpinned", true, false);
     aTab.dispatchEvent(event);
-  }
+  },
 
   previewTab(aTab, aCallback) {
     let currentTab = this.selectedTab;
     try {
       // Suppress focus, ownership and selected tab changes
       this._previewMode = true;
       this.selectedTab = aTab;
       aCallback();
     } finally {
       this.selectedTab = currentTab;
       this._previewMode = false;
     }
-  }
+  },
 
   syncThrobberAnimations(aTab) {
     aTab.ownerGlobal.promiseDocumentFlushed(() => {
       if (!aTab.parentNode) {
         return;
       }
 
       const animations =
@@ -602,40 +599,40 @@ class TabBrowser {
           // the playState, since reading the playState of
           // a CSSAnimation object will flush style.
           if (animation.currentTime !== null) {
             animation.startTime = firstStartTime;
           }
         }
       });
     });
-  }
+  },
 
   getBrowserAtIndex(aIndex) {
     return this.browsers[aIndex];
-  }
+  },
 
   getBrowserIndexForDocument(aDocument) {
     var tab = this._getTabForContentWindow(aDocument.defaultView);
     return tab ? tab._tPos : -1;
-  }
+  },
 
   getBrowserForDocument(aDocument) {
     var tab = this._getTabForContentWindow(aDocument.defaultView);
     return tab ? tab.linkedBrowser : null;
-  }
+  },
 
   getBrowserForContentWindow(aWindow) {
     var tab = this._getTabForContentWindow(aWindow);
     return tab ? tab.linkedBrowser : null;
-  }
+  },
 
   getBrowserForOuterWindowID(aID) {
     return this._outerWindowIDBrowserMap.get(aID);
-  }
+  },
 
   _getTabForContentWindow(aWindow) {
     // When not using remote browsers, we can take a fast path by getting
     // directly from the content window to the browser without looping
     // over all browsers.
     if (!gMultiProcessBrowser) {
       let browser = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIWebNavigation)
@@ -646,52 +643,52 @@ class TabBrowser {
 
     for (let i = 0; i < this.browsers.length; i++) {
       // NB: We use contentWindowAsCPOW so that this code works both
       // for remote browsers as well. aWindow may be a CPOW.
       if (this.browsers[i].contentWindowAsCPOW == aWindow)
         return this.tabs[i];
     }
     return null;
-  }
+  },
 
   getTabForBrowser(aBrowser) {
     return this._tabForBrowser.get(aBrowser);
-  }
+  },
 
   getNotificationBox(aBrowser) {
     return this.getSidebarContainer(aBrowser).parentNode;
-  }
+  },
 
   getSidebarContainer(aBrowser) {
     return this.getBrowserContainer(aBrowser).parentNode;
-  }
+  },
 
   getBrowserContainer(aBrowser) {
     return (aBrowser || this.mCurrentBrowser).parentNode.parentNode;
-  }
+  },
 
   getTabModalPromptBox(aBrowser) {
     let browser = (aBrowser || this.mCurrentBrowser);
     if (!browser.tabModalPromptBox) {
       browser.tabModalPromptBox = new TabModalPromptBox(browser);
     }
     return browser.tabModalPromptBox;
-  }
+  },
 
   getTabFromAudioEvent(aEvent) {
     if (!Services.prefs.getBoolPref("browser.tabs.showAudioPlayingIcon") ||
       !aEvent.isTrusted) {
       return null;
     }
 
     var browser = aEvent.originalTarget;
     var tab = this.getTabForBrowser(browser);
     return tab;
-  }
+  },
 
   _callProgressListeners(aBrowser, aMethod, aArguments, aCallGlobalListeners, aCallTabsListeners) {
     var rv = true;
 
     function callListeners(listeners, args) {
       for (let p of listeners) {
         if (aMethod in p) {
           try {
@@ -717,17 +714,17 @@ class TabBrowser {
     // eslint-disable-next-line mozilla/no-compare-against-boolean-literals
     if (aCallTabsListeners != false) {
       aArguments.unshift(aBrowser);
 
       callListeners(this.mTabsProgressListeners, aArguments);
     }
 
     return rv;
-  }
+  },
 
   /**
    * Determine if a URI is an about: page pointing to a local resource.
    */
   _isLocalAboutURI(aURI, aResolvedURI) {
     if (!aURI.schemeIs("about")) {
       return false;
     }
@@ -747,28 +744,28 @@ class TabBrowser {
         Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, // securityFlags
         Ci.nsIContentPolicy.TYPE_OTHER // contentPolicyType
       ).URI;
       return resolvedURI.schemeIs("jar") || resolvedURI.schemeIs("file");
     } catch (ex) {
       // aURI might be invalid.
       return false;
     }
-  }
+  },
 
   storeIcon(aBrowser, aURI, aLoadingPrincipal, aRequestContextID) {
     try {
       if (!(aURI instanceof Ci.nsIURI)) {
         aURI = makeURI(aURI);
       }
       PlacesUIUtils.loadFavicon(aBrowser, aLoadingPrincipal, aURI, aRequestContextID);
     } catch (ex) {
       Cu.reportError(ex);
     }
-  }
+  },
 
   setIcon(aTab, aURI, aLoadingPrincipal, aRequestContextID) {
     let browser = this.getBrowserForTab(aTab);
     browser.mIconURL = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
     let loadingPrincipal = aLoadingPrincipal ||
       Services.scriptSecurityManager.getSystemPrincipal();
     let requestContextID = aRequestContextID || 0;
     let sizedIconUrl = browser.mIconURL || "";
@@ -786,36 +783,36 @@ class TabBrowser {
         aTab.removeAttribute("iconloadingprincipal");
         delete browser.mIconLoadingPrincipal;
         aTab.removeAttribute("image");
       }
       this._tabAttrModified(aTab, ["image"]);
     }
 
     this._callProgressListeners(browser, "onLinkIconAvailable", [browser.mIconURL]);
-  }
+  },
 
   getIcon(aTab) {
     let browser = aTab ? this.getBrowserForTab(aTab) : this.selectedBrowser;
     return browser.mIconURL;
-  }
+  },
 
   setPageInfo(aURL, aDescription, aPreviewImage) {
     if (aURL) {
       let pageInfo = { url: aURL, description: aDescription, previewImageURL: aPreviewImage };
       PlacesUtils.history.update(pageInfo).catch(Cu.reportError);
     }
-  }
+  },
 
   shouldLoadFavIcon(aURI) {
     return (aURI &&
             Services.prefs.getBoolPref("browser.chrome.site_icons") &&
             Services.prefs.getBoolPref("browser.chrome.favicons") &&
             ("schemeIs" in aURI) && (aURI.schemeIs("http") || aURI.schemeIs("https")));
-  }
+  },
 
   useDefaultIcon(aTab) {
     let browser = this.getBrowserForTab(aTab);
     let documentURI = browser.documentURI;
     let requestContextID = browser.contentRequestContextID;
     let loadingPrincipal = browser.contentPrincipal;
     let icon = null;
 
@@ -837,23 +834,23 @@ class TabBrowser {
       let url = documentURI.prePath + "/favicon.ico";
       if (!this.isFailedIcon(url)) {
         icon = url;
         this.storeIcon(browser, icon, loadingPrincipal, requestContextID);
       }
     }
 
     this.setIcon(aTab, icon, loadingPrincipal, requestContextID);
-  }
+  },
 
   isFailedIcon(aURI) {
     if (!(aURI instanceof Ci.nsIURI))
       aURI = makeURI(aURI);
     return PlacesUtils.favicons.isFailedFavicon(aURI);
-  }
+  },
 
   getWindowTitleForBrowser(aBrowser) {
     var newTitle = "";
     var docElement = document.documentElement;
     var sep = docElement.getAttribute("titlemenuseparator");
     let tab = this.getTabForBrowser(aBrowser);
     let docTitle;
 
@@ -886,21 +883,21 @@ class TabBrowser {
         if (uri.scheme == "about")
           newTitle = uri.spec + sep + newTitle;
         else
           newTitle = uri.prePath + sep + newTitle;
       }
     } catch (e) {}
 
     return newTitle;
-  }
+  },
 
   updateTitlebar() {
     document.title = this.getWindowTitleForBrowser(this.mCurrentBrowser);
-  }
+  },
 
   updateCurrentBrowser(aForceUpdate) {
     var newBrowser = this.getBrowserAtIndex(this.tabContainer.selectedIndex);
     if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
       return;
 
     if (!aForceUpdate) {
       document.commandDispatcher.lock();
@@ -1115,17 +1112,17 @@ class TabBrowser {
         bubbles: true,
         cancelable: true
       });
       this.dispatchEvent(event);
     }
 
     if (!aForceUpdate)
       TelemetryStopwatch.finish("FX_TAB_SWITCH_UPDATE_MS");
-  }
+  },
 
   _adjustFocusBeforeTabSwitch(oldTab, newTab) {
     if (this._previewMode) {
       return;
     }
 
     let oldBrowser = oldTab.linkedBrowser;
     let newBrowser = newTab.linkedBrowser;
@@ -1151,17 +1148,17 @@ class TabBrowser {
         gURLBar &&
         gURLBar.focused;
       if (!keepFocusOnUrlBar) {
         // Clear focus so that _adjustFocusAfterTabSwitch can detect if
         // some element has been focused and respect that.
         document.activeElement.blur();
       }
     }
-  }
+  },
 
   _adjustFocusAfterTabSwitch(newTab) {
     // Don't steal focus from the tab bar.
     if (document.activeElement == newTab)
       return;
 
     let newBrowser = this.getBrowserForTab(newTab);
 
@@ -1218,31 +1215,31 @@ class TabBrowser {
       // last clicked when switching back to that tab
       if (newFocusedElement &&
           (newFocusedElement instanceof HTMLAnchorElement ||
             newFocusedElement.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple"))
         focusFlags |= fm.FLAG_SHOWRING;
     }
 
     fm.setFocus(newBrowser, focusFlags);
-  }
+  },
 
   _tabAttrModified(aTab, aChanged) {
     if (aTab.closing)
       return;
 
     let event = new CustomEvent("TabAttrModified", {
       bubbles: true,
       cancelable: false,
       detail: {
         changed: aChanged,
       }
     });
     aTab.dispatchEvent(event);
-  }
+  },
 
   setBrowserSharing(aBrowser, aState) {
     let tab = this.getTabForBrowser(aBrowser);
     if (!tab)
       return;
 
     if (aState.sharing) {
       tab._sharingState = aState;
@@ -1254,37 +1251,37 @@ class TabBrowser {
     } else {
       tab._sharingState = null;
       tab.removeAttribute("sharing");
     }
     this._tabAttrModified(tab, ["sharing"]);
 
     if (aBrowser == this.mCurrentBrowser)
       gIdentityHandler.updateSharingIndicator();
-  }
+  },
 
   getTabSharingState(aTab) {
     // Normalize the state object for consumers (ie.extensions).
     let state = Object.assign({}, aTab._sharingState);
     return {
       camera: !!state.camera,
       microphone: !!state.microphone,
       screen: state.screen && state.screen.replace("Paused", ""),
     };
-  }
+  },
 
   setInitialTabTitle(aTab, aTitle, aOptions) {
     if (aTitle) {
       if (!aTab.getAttribute("label")) {
         aTab._labelIsInitialTitle = true;
       }
 
       this._setTabLabel(aTab, aTitle, aOptions);
     }
-  }
+  },
 
   setTabTitle(aTab) {
     var browser = this.getBrowserForTab(aTab);
     var title = browser.contentTitle;
 
     // Don't replace an initially set label with the URL while the tab
     // is loading.
     if (aTab._labelIsInitialTitle) {
@@ -1332,17 +1329,17 @@ class TabBrowser {
         } catch (ex) { /* Do nothing. */ }
       } else {
         // Still no title? Fall back to our untitled string.
         title = gTabBrowserBundle.GetStringFromName("tabs.emptyTabTitle");
       }
     }
 
     return this._setTabLabel(aTab, title, { isContentTitle });
-  }
+  },
 
   _setTabLabel(aTab, aLabel, aOptions) {
     if (!aLabel) {
       return false;
     }
 
     aTab._fullLabel = aLabel;
 
@@ -1374,17 +1371,17 @@ class TabBrowser {
       this._tabAttrModified(aTab, ["label"]);
     }
 
     if (aTab.selected) {
       this.updateTitlebar();
     }
 
     return true;
-  }
+  },
 
   loadOneTab(aURI, aReferrerURI, aCharset, aPostData, aLoadInBackground, aAllowThirdPartyFixup) {
     var aTriggeringPrincipal;
     var aReferrerPolicy;
     var aFromExternal;
     var aRelatedToCurrent;
     var aAllowMixedContent;
     var aSkipAnimation;
@@ -1457,17 +1454,17 @@ class TabBrowser {
       nextTabParentId: aNextTabParentId,
       focusUrlBar: aFocusUrlBar,
       name: aName
     });
     if (!bgLoad)
       this.selectedTab = tab;
 
     return tab;
-  }
+  },
 
   loadTabs(aURIs, aLoadInBackground, aReplace) {
     let aTriggeringPrincipal;
     let aAllowThirdPartyFixup;
     let aTargetTab;
     let aNewIndex = -1;
     let aPostDatas = [];
     let aUserContextId;
@@ -1554,17 +1551,17 @@ class TabBrowser {
       });
       if (targetTabIndex !== -1)
         this.moveTabTo(tab, ++tabNum);
     }
 
     if (firstTabAdded && !aLoadInBackground) {
       this.selectedTab = firstTabAdded;
     }
-  }
+  },
 
   updateBrowserRemoteness(aBrowser, aShouldBeRemote, aOptions) {
     aOptions = aOptions || {};
     let isRemote = aBrowser.getAttribute("remote") == "true";
 
     if (!gMultiProcessBrowser && aShouldBeRemote) {
       throw new Error("Cannot switch to remote browser in a window " +
         "without the remote tabs load context.");
@@ -1710,17 +1707,17 @@ class TabBrowser {
       this.getFindBar(tab).browser = aBrowser;
     }
 
     evt = document.createEvent("Events");
     evt.initEvent("TabRemotenessChange", true, false);
     tab.dispatchEvent(evt);
 
     return true;
-  }
+  },
 
   updateBrowserRemotenessByURL(aBrowser, aURL, aOptions) {
     aOptions = aOptions || {};
 
     if (!gMultiProcessBrowser)
       return this.updateBrowserRemoteness(aBrowser, false);
 
     let currentRemoteType = aBrowser.getAttribute("remoteType") || null;
@@ -1735,29 +1732,29 @@ class TabBrowser {
     // correct type.
     if (currentRemoteType != aOptions.remoteType ||
       aOptions.newFrameloader) {
       let remote = aOptions.remoteType != E10SUtils.NOT_REMOTE;
       return this.updateBrowserRemoteness(aBrowser, remote, aOptions);
     }
 
     return false;
-  }
+  },
 
   removePreloadedBrowser() {
     if (!this._isPreloadingEnabled()) {
       return;
     }
 
     let browser = this._getPreloadedBrowser();
 
     if (browser) {
       browser.remove();
     }
-  }
+  },
 
   _getPreloadedBrowser() {
     if (!this._isPreloadingEnabled()) {
       return null;
     }
 
     // The preloaded browser might be null.
     let browser = this._preloadedBrowser;
@@ -1772,25 +1769,25 @@ class TabBrowser {
     // in the case that the browser is remote, as remote browsers take
     // care of that themselves.
     if (browser) {
       browser.setAttribute("preloadedState", "consumed");
       browser.setAttribute("autocompletepopup", "PopupAutoComplete");
     }
 
     return browser;
-  }
+  },
 
   _isPreloadingEnabled() {
     // Preloading for the newtab page is enabled when the pref is true
     // and the URL is "about:newtab". We do not support preloading for
     // custom newtab URLs.
     return Services.prefs.getBoolPref("browser.newtab.preload") &&
       !aboutNewTabService.overridden;
-  }
+  },
 
   _createPreloadBrowser() {
     // Do nothing if we have a preloaded browser already
     // or preloading of newtab pages is disabled.
     if (this._preloadedBrowser || !this._isPreloadingEnabled()) {
       return;
     }
 
@@ -1807,21 +1804,23 @@ class TabBrowser {
       // For remote browsers, we need to make sure that the webProgress is
       // instantiated, otherwise the parent won't get informed about the state
       // of the preloaded browser until it gets attached to a tab.
       browser.webProgress;
     }
 
     browser.loadURI(BROWSER_NEW_TAB_URL);
     browser.docShellIsActive = false;
+    browser.renderLayers = true;
+    browser._urlbarFocused = true;
 
     // Make sure the preloaded browser is loaded with desired zoom level
     let tabURI = Services.io.newURI(BROWSER_NEW_TAB_URL);
     FullZoom.onLocationChange(tabURI, false, browser);
-  }
+  },
 
   _createBrowser(aParams) {
     // Supported parameters:
     // userContextId, remote, remoteType, isPreloadBrowser,
     // uriIsAboutBlank, sameProcessAsFrameLoader
 
     let b = document.createElementNS(this._XUL_NS, "browser");
     b.permanentKey = {};
@@ -1927,17 +1926,17 @@ class TabBrowser {
 
     // Prevent the superfluous initial load of a blank document
     // if we're going to load something other than about:blank.
     if (!aParams.uriIsAboutBlank) {
       b.setAttribute("nodefaultsrc", "true");
     }
 
     return b;
-  }
+  },
 
   _createLazyBrowser(aTab) {
     let browser = aTab.linkedBrowser;
 
     let names = this._browserBindingProperties;
 
     for (let i = 0; i < names.length; i++) {
       let name = names[i];
@@ -2021,17 +2020,17 @@ class TabBrowser {
       }
       Object.defineProperty(browser, name, {
         get: getter,
         set: setter,
         configurable: true,
         enumerable: true
       });
     }
-  }
+  },
 
   _insertBrowser(aTab, aInsertedOnTabCreation) {
     "use strict";
 
     // If browser is already inserted or window is closed don't do anything.
     if (aTab.linkedPanel || window.closed) {
       return;
     }
@@ -2070,32 +2069,42 @@ class TabBrowser {
       .createInstance(Ci.nsIWebProgress);
     filter.addProgressListener(tabListener, Ci.nsIWebProgress.NOTIFY_ALL);
     browser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
     this._tabListeners.set(aTab, tabListener);
     this._tabFilters.set(aTab, filter);
 
     browser.droppedLinkHandler = handleDroppedLink;
 
-    // We start our browsers out as inactive, and then maintain
-    // activeness in the tab switcher.
-    browser.docShellIsActive = false;
+    // Most of the time, we start our browser's docShells out as inactive,
+    // and then maintain activeness in the tab switcher. Preloaded about:newtab's
+    // are already created with their docShell's as inactive, but then explicitly
+    // render their layers to ensure that we can switch to them quickly. We avoid
+    // setting docShellIsActive to false again in this case, since that'd cause
+    // the layers for the preloaded tab to be dropped, and we'd see a flash
+    // of empty content instead.
+    //
+    // So for all browsers except for the preloaded case, we set the browser
+    // docShell to inactive.
+    if (!usingPreloadedContent) {
+      browser.docShellIsActive = false;
+    }
 
     // When addTab() is called with an URL that is not "about:blank" we
     // set the "nodefaultsrc" attribute that prevents a frameLoader
     // from being created as soon as the linked <browser> is inserted
     // into the DOM. We thus have to register the new outerWindowID
     // for non-remote browsers after we have called browser.loadURI().
     if (remoteType == E10SUtils.NOT_REMOTE) {
       this._outerWindowIDBrowserMap.set(browser.outerWindowID, browser);
     }
 
     var evt = new CustomEvent("TabBrowserInserted", { bubbles: true, detail: { insertedOnTabCreation: aInsertedOnTabCreation } });
     aTab.dispatchEvent(evt);
-  }
+  },
 
   discardBrowser(aBrowser, aForceDiscard) {
     "use strict";
 
     let tab = this.getTabForBrowser(aBrowser);
 
     let permitUnloadFlags = aForceDiscard ? aBrowser.dontPromptAndUnload : aBrowser.dontPromptAndDontUnload;
 
@@ -2144,17 +2153,17 @@ class TabBrowser {
     let notificationbox = this.getNotificationBox(aBrowser);
     this.mPanelContainer.removeChild(notificationbox);
     tab.removeAttribute("linkedpanel");
 
     this._createLazyBrowser(tab);
 
     let evt = new CustomEvent("TabBrowserDiscarded", { bubbles: true });
     tab.dispatchEvent(evt);
-  }
+  },
 
   // eslint-disable-next-line complexity
   addTab(aURI, aReferrerURI, aCharset, aPostData, aOwner, aAllowThirdPartyFixup) {
     "use strict";
 
     var aTriggeringPrincipal;
     var aReferrerPolicy;
     var aFromExternal;
@@ -2481,17 +2490,17 @@ class TabBrowser {
     if (animate) {
       requestAnimationFrame(function() {
         // kick the animation off
         t.setAttribute("fadein", "true");
       });
     }
 
     return t;
-  }
+  },
 
   warnAboutClosingTabs(aCloseTabs, aTab) {
     var tabsToClose;
     switch (aCloseTabs) {
       case this.closingTabsEnum.ALL:
         tabsToClose = this.tabs.length - this._removingTabs.length -
           gBrowser._numPinnedTabs;
         break;
@@ -2544,29 +2553,29 @@ class TabBrowser {
         warnOnClose);
     var reallyClose = (buttonPressed == 0);
 
     // don't set the pref unless they press OK and it's false
     if (aCloseTabs == this.closingTabsEnum.ALL && reallyClose && !warnOnClose.value)
       Services.prefs.setBoolPref(pref, false);
 
     return reallyClose;
-  }
+  },
 
   getTabsToTheEndFrom(aTab) {
     let tabsToEnd = [];
     let tabs = this.visibleTabs;
     for (let i = tabs.length - 1; i >= 0; --i) {
       if (tabs[i] == aTab || tabs[i].pinned) {
         break;
       }
       tabsToEnd.push(tabs[i]);
     }
     return tabsToEnd;
-  }
+  },
 
   removeTabsToTheEndFrom(aTab, aParams) {
     if (!this.warnAboutClosingTabs(this.closingTabsEnum.TO_END, aTab))
       return;
 
     let removeTab = tab => {
       // Avoid changing the selected browser several times.
       if (tab.selected)
@@ -2580,17 +2589,17 @@ class TabBrowser {
     for (let i = tabs.length - 1; i >= 0; --i) {
       let tab = tabs[i];
       if (this._hasBeforeUnload(tab))
         tabsWithBeforeUnload.push(tab);
       else
         removeTab(tab);
     }
     tabsWithBeforeUnload.forEach(removeTab);
-  }
+  },
 
   removeAllTabsBut(aTab) {
     if (!this.warnAboutClosingTabs(this.closingTabsEnum.OTHER)) {
       return;
     }
 
     let tabs = this.visibleTabs.reverse();
     this.selectedTab = aTab;
@@ -2603,21 +2612,21 @@ class TabBrowser {
           tabsWithBeforeUnload.push(tab);
         else
           this.removeTab(tab, { animate: true });
       }
     }
     for (let tab of tabsWithBeforeUnload) {
       this.removeTab(tab, { animate: true });
     }
-  }
+  },
 
   removeCurrentTab(aParams) {
     this.removeTab(this.mCurrentTab, aParams);
-  }
+  },
 
   removeTab(aTab, aParams) {
     if (aParams) {
       var animate = aParams.animate;
       var byMouse = aParams.byMouse;
       var skipPermitUnload = aParams.skipPermitUnload;
     }
 
@@ -2676,24 +2685,24 @@ class TabBrowser {
 
     setTimeout(function(tab, tabbrowser) {
       if (tab.parentNode &&
           window.getComputedStyle(tab).maxWidth == "0.1px") {
         NS_ASSERT(false, "Giving up waiting for the tab closing animation to finish (bug 608589)");
         tabbrowser._endRemoveTab(tab);
       }
     }, 3000, aTab, this);
-  }
+  },
 
   _hasBeforeUnload(aTab) {
     let browser = aTab.linkedBrowser;
     return browser.isRemoteBrowser && browser.frameLoader &&
            browser.frameLoader.tabParent &&
            browser.frameLoader.tabParent.hasBeforeUnload;
-  }
+  },
 
   _beginRemoveTab(aTab, aAdoptedByTab, aCloseWindowWithLastTab, aCloseWindowFastpath, aSkipPermitUnload) {
     if (aTab.closing ||
       this._windowIsClosing)
       return false;
 
     var browser = this.getBrowserForTab(aTab);
     if (!aSkipPermitUnload && !aAdoptedByTab &&
@@ -2823,17 +2832,17 @@ class TabBrowser {
     // Remove this tab as the owner of any other tabs, since it's going away.
     for (let tab of this.tabs) {
       if ("owner" in tab && tab.owner == aTab)
         // |tab| is a child of the tab we're removing, make it an orphan
         tab.owner = null;
     }
 
     return true;
-  }
+  },
 
   _endRemoveTab(aTab) {
     if (!aTab || !aTab._endRemoveArgs)
       return;
 
     var [aCloseWindow, aNewTab] = aTab._endRemoveArgs;
     aTab._endRemoveArgs = null;
 
@@ -2943,17 +2952,17 @@ class TabBrowser {
     // stopwatches here instead.
     TelemetryStopwatch.finish("FX_TAB_CLOSE_TIME_ANIM_MS", aTab,
       true /* aCanceledOkay */ );
     TelemetryStopwatch.finish("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab,
       true /* aCanceledOkay */ );
 
     if (aCloseWindow)
       this._windowIsClosing = closeWindow(true, window.warnAboutClosingWindow);
-  }
+  },
 
   _findTabToBlurTo(aTab) {
     if (!aTab.selected) {
       return null;
     }
 
     if (aTab.owner &&
         !aTab.owner.hidden &&
@@ -2981,21 +2990,21 @@ class TabBrowser {
       tab = aTab;
 
       do {
         tab = tab.previousSibling;
       } while (tab && !remainingTabs.includes(tab));
     }
 
     return tab;
-  }
+  },
 
   _blurTab(aTab) {
     this.selectedTab = this._findTabToBlurTo(aTab);
-  }
+  },
 
   swapBrowsersAndCloseOther(aOurTab, aOtherTab) {
     // Do not allow transfering a private tab to a non-private window
     // and vice versa.
     if (PrivateBrowsingUtils.isWindowPrivate(window) !=
       PrivateBrowsingUtils.isWindowPrivate(aOtherTab.ownerGlobal))
       return;
 
@@ -3128,17 +3137,17 @@ class TabBrowser {
     // If the tab was already selected (this happpens in the scenario
     // of replaceTabWithWindow), notify onLocationChange, etc.
     if (aOurTab.selected)
       this.updateCurrentBrowser(true);
 
     if (modifiedAttrs.length) {
       this._tabAttrModified(aOurTab, modifiedAttrs);
     }
-  }
+  },
 
   swapBrowsers(aOurTab, aOtherTab, aFlags) {
     let otherBrowser = aOtherTab.linkedBrowser;
     let otherTabBrowser = otherBrowser.getTabBrowser();
 
     // We aren't closing the other tab so, we also need to swap its tablisteners.
     let filter = otherTabBrowser._tabFilters.get(aOtherTab);
     let tabListener = otherTabBrowser._tabListeners.get(aOtherTab);
@@ -3150,17 +3159,17 @@ class TabBrowser {
 
     // Restore the listeners for the swapped in tab.
     tabListener = new otherTabBrowser.ownerGlobal.TabProgressListener(aOtherTab, otherBrowser, false, false);
     otherTabBrowser._tabListeners.set(aOtherTab, tabListener);
 
     const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
     filter.addProgressListener(tabListener, notifyAll);
     otherBrowser.webProgress.addProgressListener(filter, notifyAll);
-  }
+  },
 
   _swapBrowserDocShells(aOurTab, aOtherBrowser, aFlags, aStateFlags) {
     // aOurTab's browser needs to be inserted now if it hasn't already.
     this._insertBrowser(aOurTab);
 
     // Unhook our progress listener
     const filter = this._tabFilters.get(aOurTab);
     let tabListener = this._tabListeners.get(aOurTab);
@@ -3216,106 +3225,106 @@ class TabBrowser {
 
     // Restore the progress listener
     tabListener = new TabProgressListener(aOurTab, ourBrowser, false, false, aStateFlags);
     this._tabListeners.set(aOurTab, tabListener);
 
     const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
     filter.addProgressListener(tabListener, notifyAll);
     ourBrowser.webProgress.addProgressListener(filter, notifyAll);
-  }
+  },
 
   _swapRegisteredOpenURIs(aOurBrowser, aOtherBrowser) {
     // Swap the registeredOpenURI properties of the two browsers
     let tmp = aOurBrowser.registeredOpenURI;
     delete aOurBrowser.registeredOpenURI;
     if (aOtherBrowser.registeredOpenURI) {
       aOurBrowser.registeredOpenURI = aOtherBrowser.registeredOpenURI;
       delete aOtherBrowser.registeredOpenURI;
     }
     if (tmp) {
       aOtherBrowser.registeredOpenURI = tmp;
     }
-  }
+  },
 
   reloadAllTabs() {
     let tabs = this.visibleTabs;
     let l = tabs.length;
     for (var i = 0; i < l; i++) {
       try {
         this.getBrowserForTab(tabs[i]).reload();
       } catch (e) {
         // ignore failure to reload so others will be reloaded
       }
     }
-  }
+  },
 
   reloadTab(aTab) {
     let browser = this.getBrowserForTab(aTab);
     // Reset temporary permissions on the current tab. This is done here
     // because we only want to reset permissions on user reload.
     SitePermissions.clearTemporaryPermissions(browser);
     browser.reload();
-  }
+  },
 
   addProgressListener(aListener) {
     if (arguments.length != 1) {
       Cu.reportError("gBrowser.addProgressListener was " +
         "called with a second argument, " +
         "which is not supported. See bug " +
         "608628. Call stack: " + new Error().stack);
     }
 
     this.mProgressListeners.push(aListener);
-  }
+  },
 
   removeProgressListener(aListener) {
     this.mProgressListeners =
       this.mProgressListeners.filter(l => l != aListener);
-  }
+  },
 
   addTabsProgressListener(aListener) {
     this.mTabsProgressListeners.push(aListener);
-  }
+  },
 
   removeTabsProgressListener(aListener) {
     this.mTabsProgressListeners =
       this.mTabsProgressListeners.filter(l => l != aListener);
-  }
+  },
 
   getBrowserForTab(aTab) {
     return aTab.linkedBrowser;
-  }
+  },
 
   showOnlyTheseTabs(aTabs) {
     for (let tab of this.tabs) {
       if (!aTabs.includes(tab))
         this.hideTab(tab);
       else
         this.showTab(tab);
     }
 
     this.tabContainer._handleTabSelect(true);
-  }
+  },
 
   showTab(aTab) {
     if (aTab.hidden) {
       aTab.removeAttribute("hidden");
       this._visibleTabs = null; // invalidate cache
 
       this.tabContainer._updateCloseButtons();
 
       this.tabContainer._setPositionalAttributes();
 
       let event = document.createEvent("Events");
       event.initEvent("TabShow", true, false);
       aTab.dispatchEvent(event);
       SessionStore.deleteTabValue(aTab, "hiddenBy");
     }
-  }
+  },
 
   hideTab(aTab, aSource) {
     if (!aTab.hidden && !aTab.pinned && !aTab.selected &&
         !aTab.closing && !aTab._sharingState) {
       aTab.setAttribute("hidden", "true");
       this._visibleTabs = null; // invalidate cache
 
       this.tabContainer._updateCloseButtons();
@@ -3324,17 +3333,17 @@ class TabBrowser {
 
       let event = document.createEvent("Events");
       event.initEvent("TabHide", true, false);
       aTab.dispatchEvent(event);
       if (aSource) {
         SessionStore.setTabValue(aTab, "hiddenBy", aSource);
       }
     }
-  }
+  },
 
   selectTabAtIndex(aIndex, aEvent) {
     let tabs = this.visibleTabs;
 
     // count backwards for aIndex < 0
     if (aIndex < 0) {
       aIndex += tabs.length;
       // clamp at index 0 if still negative.
@@ -3346,17 +3355,17 @@ class TabBrowser {
     }
 
     this.selectedTab = tabs[aIndex];
 
     if (aEvent) {
       aEvent.preventDefault();
       aEvent.stopPropagation();
     }
-  }
+  },
 
   /**
    * Moves a tab to a new browser window, unless it's already the only tab
    * in the current window, in which case this will do nothing.
    */
   replaceTabWithWindow(aTab, aOptions) {
     if (this.tabs.length == 1)
       return null;
@@ -3370,17 +3379,17 @@ class TabBrowser {
     // content area when the docshells are swapped.
     if (this.animationsEnabled) {
       aTab.style.maxWidth = ""; // ensure that fade-out transition happens
       aTab.removeAttribute("fadein");
     }
 
     // tell a new window to take the "dropped" tab
     return window.openDialog(getBrowserURL(), "_blank", options, aTab);
-  }
+  },
 
   moveTabTo(aTab, aIndex, aKeepRelatedTabs) {
     var oldPosition = aTab._tPos;
     if (oldPosition == aIndex)
       return;
 
     // Don't allow mixing pinned and unpinned tabs.
     if (aTab.pinned)
@@ -3435,28 +3444,28 @@ class TabBrowser {
     if (aTab.pinned)
       this.tabContainer._positionPinnedTabs();
 
     this.tabContainer._setPositionalAttributes();
 
     var evt = document.createEvent("UIEvents");
     evt.initUIEvent("TabMove", true, false, window, oldPosition);
     aTab.dispatchEvent(evt);
-  }
+  },
 
   moveTabForward() {
     let nextTab = this.mCurrentTab.nextSibling;
     while (nextTab && nextTab.hidden)
       nextTab = nextTab.nextSibling;
 
     if (nextTab)
       this.moveTabTo(this.mCurrentTab, nextTab._tPos);
     else if (this.arrowKeysShouldWrap)
       this.moveTabToStart();
-  }
+  },
 
   /**
    * Adopts a tab from another browser window, and inserts it at aIndex
    */
   adoptTab(aTab, aIndex, aSelectTab) {
     // Swap the dropped tab with a new one we create and then close
     // it in the other window (making it seem to have moved between
     // windows). We also ensure that the tab we create to swap into has
@@ -3502,102 +3511,102 @@ class TabBrowser {
 
     if (aSelectTab) {
       // Call updateCurrentBrowser to make sure the URL bar is up to date
       // for our new tab after we've done swapBrowsersAndCloseOther.
       this.updateCurrentBrowser(true);
     }
 
     return newTab;
-  }
+  },
 
   moveTabBackward() {
     let previousTab = this.mCurrentTab.previousSibling;
     while (previousTab && previousTab.hidden)
       previousTab = previousTab.previousSibling;
 
     if (previousTab)
       this.moveTabTo(this.mCurrentTab, previousTab._tPos);
     else if (this.arrowKeysShouldWrap)
       this.moveTabToEnd();
-  }
+  },
 
   moveTabToStart() {
     var tabPos = this.mCurrentTab._tPos;
     if (tabPos > 0)
       this.moveTabTo(this.mCurrentTab, 0);
-  }
+  },
 
   moveTabToEnd() {
     var tabPos = this.mCurrentTab._tPos;
     if (tabPos < this.browsers.length - 1)
       this.moveTabTo(this.mCurrentTab, this.browsers.length - 1);
-  }
+  },
 
   moveTabOver(aEvent) {
     let direction = window.getComputedStyle(document.documentElement).direction;
     if ((direction == "ltr" && aEvent.keyCode == KeyEvent.DOM_VK_RIGHT) ||
         (direction == "rtl" && aEvent.keyCode == KeyEvent.DOM_VK_LEFT)) {
       this.moveTabForward();
     } else {
       this.moveTabBackward();
     }
-  }
+  },
 
   /**
    * @param   aTab
    *          Can be from a different window as well
    * @param   aRestoreTabImmediately
    *          Can defer loading of the tab contents
    */
   duplicateTab(aTab, aRestoreTabImmediately) {
     return SessionStore.duplicateTab(window, aTab, 0, aRestoreTabImmediately);
-  }
+  },
 
   activateBrowserForPrintPreview(aBrowser) {
     this._printPreviewBrowsers.add(aBrowser);
     if (this._switcher) {
       this._switcher.activateBrowserForPrintPreview(aBrowser);
     }
     aBrowser.docShellIsActive = true;
-  }
+  },
 
   deactivatePrintPreviewBrowsers() {
     let browsers = this._printPreviewBrowsers;
     this._printPreviewBrowsers = new Set();
     for (let browser of browsers) {
       browser.docShellIsActive = this.shouldActivateDocShell(browser);
     }
-  }
+  },
 
   /**
    * Returns true if a given browser's docshell should be active.
    */
   shouldActivateDocShell(aBrowser) {
     if (this._switcher) {
       return this._switcher.shouldActivateDocShell(aBrowser);
     }
     return (aBrowser == this.selectedBrowser &&
             window.windowState != window.STATE_MINIMIZED &&
             !window.isFullyOccluded) ||
             this._printPreviewBrowsers.has(aBrowser);
-  }
+  },
 
   _getSwitcher() {
     if (!this._switcher) {
       this._switcher = new this.AsyncTabSwitcher(this);
     }
     return this._switcher;
-  }
+  },
 
   warmupTab(aTab) {
     if (gMultiProcessBrowser) {
       this._getSwitcher().warmupTab(aTab);
     }
-  }
+  },
 
   _handleKeyDownEvent(aEvent) {
     if (!aEvent.isTrusted) {
       // Don't let untrusted events mess with tabs.
       return;
     }
 
     if (aEvent.altKey)
@@ -3622,17 +3631,17 @@ class TabBrowser {
     if (AppConstants.platform != "macosx") {
       if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
           aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
           !this.mCurrentTab.pinned) {
         this.removeCurrentTab({ animate: true });
         aEvent.preventDefault();
       }
     }
-  }
+  },
 
   _handleKeyPressEventMac(aEvent) {
     if (!aEvent.isTrusted) {
       // Don't let untrusted events mess with tabs.
       return;
     }
 
     if (aEvent.altKey)
@@ -3648,17 +3657,17 @@ class TabBrowser {
           offset = -1;
         case "{".charCodeAt(0):
           if (window.getComputedStyle(document.documentElement).direction == "ltr")
             offset *= -1;
           this.tabContainer.advanceSelectedTab(offset, true);
           aEvent.preventDefault();
       }
     }
-  }
+  },
 
   createTooltip(event) {
     event.stopPropagation();
     var tab = document.tooltipNode;
     if (tab.localName != "tab") {
       event.preventDefault();
       return;
     }
@@ -3701,17 +3710,17 @@ class TabBrowser {
         label += " (pid " + tab.linkedBrowser.frameLoader.tabParent.osPid + ")";
       }
       if (tab.userContextId) {
         label = gTabBrowserBundle.formatStringFromName("tabs.containers.tooltip", [label, ContextualIdentityService.getUserContextLabel(tab.userContextId)], 2);
       }
     }
 
     event.target.setAttribute("label", label);
-  }
+  },
 
   handleEvent(aEvent) {
     switch (aEvent.type) {
       case "keydown":
         this._handleKeyDownEvent(aEvent);
         break;
       case "keypress":
         this._handleKeyPressEventMac(aEvent);
@@ -3720,17 +3729,17 @@ class TabBrowser {
       case "occlusionstatechange":
         if (aEvent.target == window && !this._switcher) {
           this.mCurrentBrowser.preserveLayers(
             window.windowState == window.STATE_MINIMIZED || window.isFullyOccluded);
           this.mCurrentBrowser.docShellIsActive = this.shouldActivateDocShell(this.mCurrentBrowser);
         }
         break;
     }
-  }
+  },
 
   receiveMessage(aMessage) {
     let data = aMessage.data;
     let browser = aMessage.target;
 
     switch (aMessage.name) {
       case "DOMTitleChanged":
       {
@@ -3872,17 +3881,17 @@ class TabBrowser {
             "chrome://browser/skin/notification-icons/popup.svg",
             notificationBox.PRIORITY_INFO_MEDIUM,
             buttons);
         }
         break;
       }
     }
     return undefined;
-  }
+  },
 
   observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "contextual-identity-updated":
       {
         for (let tab of this.tabs) {
           if (tab.getAttribute("usercontextid") == aData) {
             ContextualIdentityService.setTabStyle(tab);
@@ -3892,74 +3901,36 @@ class TabBrowser {
       }
       case "nsPref:changed":
       {
         // This is the only pref observed.
         this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind");
         break;
       }
     }
-  }
-
-  _updateNewTabVisibility() {
-    // Helper functions to help deal with customize mode wrapping some items
-    let wrap = n => n.parentNode.localName == "toolbarpaletteitem" ? n.parentNode : n;
-    let unwrap = n => n && n.localName == "toolbarpaletteitem" ? n.firstElementChild : n;
-
-    let sib = this.tabContainer;
-    do {
-      sib = unwrap(wrap(sib).nextElementSibling);
-    } while (sib && sib.hidden);
-
-    const kAttr = "hasadjacentnewtabbutton";
-    if (sib && sib.id == "new-tab-button") {
-      this.tabContainer.setAttribute(kAttr, "true");
-    } else {
-      this.tabContainer.removeAttribute(kAttr);
-    }
-  }
-
-  onWidgetAfterDOMChange(aNode, aNextNode, aContainer) {
-    if (aContainer.ownerDocument == document &&
-        aContainer.id == "TabsToolbar") {
-      this._updateNewTabVisibility();
-    }
-  }
-
-  onAreaNodeRegistered(aArea, aContainer) {
-    if (aContainer.ownerDocument == document &&
-        aArea == "TabsToolbar") {
-      this._updateNewTabVisibility();
-    }
-  }
-
-  onAreaReset(aArea, aContainer) {
-    this.onAreaNodeRegistered(aArea, aContainer);
-  }
+  },
 
   _generateUniquePanelID() {
     if (!this._uniquePanelIDCounter) {
       this._uniquePanelIDCounter = 0;
     }
 
     let outerID = window.QueryInterface(Ci.nsIInterfaceRequestor)
                         .getInterface(Ci.nsIDOMWindowUtils)
                         .outerWindowID;
 
     // We want panel IDs to be globally unique, that's why we include the
     // window ID. We switched to a monotonic counter as Date.now() lead
     // to random failures because of colliding IDs.
     return "panel-" + outerID + "-" + (++this._uniquePanelIDCounter);
-  }
+  },
 
   destroy() {
     Services.obs.removeObserver(this, "contextual-identity-updated");
 
-    CustomizableUI.removeListener(this);
-
     for (let tab of this.tabs) {
       let browser = tab.linkedBrowser;
       if (browser.registeredOpenURI) {
         this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI,
           browser.getAttribute("usercontextid") || 0);
         delete browser.registeredOpenURI;
       }
 
@@ -3994,17 +3965,17 @@ class TabBrowser {
       window.messageManager.removeMessageListener("contextmenu", this);
 
       if (this._switcher) {
         this._switcher.destroy();
       }
     }
 
     Services.prefs.removeObserver("accessibility.typeaheadfind", this);
-  }
+  },
 
   _setupEventListeners() {
     this.addEventListener("DOMWindowClose", (event) => {
       if (!event.isTrusted)
         return;
 
       if (this.tabs.length == 1) {
         // We already did PermitUnload in nsGlobalWindow::Close
@@ -4202,18 +4173,18 @@ class TabBrowser {
       if (tab.hasAttribute("activemedia-blocked")) {
         tab.removeAttribute("activemedia-blocked");
         this._tabAttrModified(tab, ["activemedia-blocked"]);
         let hist = Services.telemetry.getHistogramById("TAB_AUDIO_INDICATOR_USED");
         hist.add(2 /* unblockByVisitingTab */ );
         tab.finishMediaBlockTimer();
       }
     });
-  }
-}
+  },
+};
 
 /**
  * A web progress listener object definition for a given tab.
  */
 class TabProgressListener {
   constructor(aTab, aBrowser, aStartsBlank, aWasPreloadedBrowser, aOrigStateFlags) {
     let stateFlags = aOrigStateFlags || 0;
     // Initialize mStateFlags to non-zero e.g. when creating a progress
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -121,22 +121,27 @@
 
           window.addEventListener("resize", this);
           window.addEventListener("DOMContentLoaded", this);
 
           Services.prefs.addObserver("privacy.userContext", this);
           this.observe(null, "nsPref:changed", "privacy.userContext.enabled");
 
           this._setPositionalAttributes();
+
+          CustomizableUI.addListener(this);
+          this._updateNewTabVisibility();
         ]]>
       </constructor>
 
       <destructor>
         <![CDATA[
           Services.prefs.removeObserver("privacy.userContext", this);
+
+          CustomizableUI.removeListener(this);
         ]]>
       </destructor>
 
       <field name="tabbox" readonly="true">
         this.tabbrowser.tabbox;
       </field>
 
       <field name="contextMenu" readonly="true">
@@ -903,16 +908,67 @@
           // If the tab's browser is lazy, we need to `_insertBrowser` in order
           // to have a linkedPanel.  This will also serve to bind the browser
           // and make it ready to use when the tab is selected.
           this.tabbrowser._insertBrowser(aTab);
           return document.getElementById(aTab.linkedPanel);
         ]]>
         </body>
       </method>
+
+      <method name="_updateNewTabVisibility">
+        <body><![CDATA[
+          // Helper functions to help deal with customize mode wrapping some items
+          let wrap = n => n.parentNode.localName == "toolbarpaletteitem" ? n.parentNode : n;
+          let unwrap = n => n && n.localName == "toolbarpaletteitem" ? n.firstElementChild : n;
+
+          let sib = this;
+          do {
+            sib = unwrap(wrap(sib).nextElementSibling);
+          } while (sib && sib.hidden);
+
+          const kAttr = "hasadjacentnewtabbutton";
+          if (sib && sib.id == "new-tab-button") {
+            this.setAttribute(kAttr, "true");
+          } else {
+            this.removeAttribute(kAttr);
+          }
+        ]]></body>
+      </method>
+
+      <method name="onWidgetAfterDOMChange">
+        <parameter name="aNode"/>
+        <parameter name="aNextNode"/>
+        <parameter name="aContainer"/>
+        <body><![CDATA[
+          if (aContainer.ownerDocument == document &&
+              aContainer.id == "TabsToolbar") {
+            this._updateNewTabVisibility();
+          }
+        ]]></body>
+      </method>
+
+      <method name="onAreaNodeRegistered">
+        <parameter name="aArea"/>
+        <parameter name="aContainer"/>
+        <body><![CDATA[
+          if (aContainer.ownerDocument == document &&
+              aArea == "TabsToolbar") {
+            this._updateNewTabVisibility();
+          }
+        ]]></body>
+      </method>
+
+      <method name="onAreaReset">
+        <parameter name="aArea"/>
+        <parameter name="aContainer"/>
+        <body><![CDATA[
+          this.onAreaNodeRegistered(aArea, aContainer);
+        ]]></body>
+      </method>
     </implementation>
 
     <handlers>
       <handler event="TabSelect" action="this._handleTabSelect();"/>
 
       <handler event="transitionend"><![CDATA[
         if (event.propertyName != "max-width")
           return;
deleted file mode 100644
--- a/browser/base/content/test/newtab/.eslintrc.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-module.exports = {
-  "extends": [
-    "plugin:mozilla/browser-test"
-  ]
-};
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser.ini
+++ /dev/null
@@ -1,52 +0,0 @@
-[DEFAULT]
-skip-if = true # Bug 1433133 to remove; previously skipped for intermittents, e.g., Bug 1243103, Bug 1243398
-support-files =
-  head.js
-
-[browser_newtab_1188015.js]
-[browser_newtab_background_captures.js]
-[browser_newtab_block.js]
-[browser_newtab_bug721442.js]
-[browser_newtab_bug722273.js]
-skip-if = (os == "mac" && debug) # temporary skip-if due to increase in intermittent failures on Mac debug - bug 1119906
-[browser_newtab_bug723102.js]
-[browser_newtab_bug723121.js]
-[browser_newtab_bug725996.js]
-skip-if = (os == "mac" || os == "win") && debug # bug 1338848
-[browser_newtab_bug734043.js]
-[browser_newtab_bug735987.js]
-[browser_newtab_bug752841.js]
-[browser_newtab_bug765628.js]
-skip-if = (os == "mac" || os == "win") && debug # bug 1338836
-[browser_newtab_bug876313.js]
-[browser_newtab_bug991111.js]
-[browser_newtab_bug991210.js]
-[browser_newtab_bug998387.js]
-[browser_newtab_bug1271075.js]
-[browser_newtab_disable.js]
-[browser_newtab_drag_drop.js]
-[browser_newtab_drag_drop_ext.js]
-# temporary until determine why more intermittent on VM
-subsuite = clipboard
-[browser_newtab_drop_preview.js]
-[browser_newtab_focus.js]
-[browser_newtab_fullscreen_focus.js]
-skip-if = os == "mac" # bug 1394963
-[browser_newtab_perwindow_private_browsing.js]
-[browser_newtab_reflow_load.js]
-support-files =
-  content-reflows.js
-[browser_newtab_search.js]
-support-files =
-  searchEngineNoLogo.xml
-  searchEngineFavicon.xml
-  searchEngine1xLogo.xml
-  searchEngine2xLogo.xml
-  searchEngine1x2xLogo.xml
-  ../general/searchSuggestionEngine.xml
-  ../general/searchSuggestionEngine.sjs
-[browser_newtab_undo.js]
-# temporary until determine why more intermittent on VM
-subsuite = clipboard
-[browser_newtab_unpin.js]
-[browser_newtab_update.js]
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_1188015.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-gDirectorySource = "data:application/json," + JSON.stringify({
-  "directory": [{
-    url: "http://example1.com/",
-    enhancedImageURI: "data:image/png;base64,helloWORLD2",
-    title: "title1",
-    type: "affiliate",
-    titleBgColor: "green"
-  }]
-});
-
-add_task(async function() {
-  await pushPrefs(["browser.newtab.preload", false]);
-
-  // Make the page have a directory link
-  await setLinks([]);
-  await addNewTabPageTab();
-
-  let color = await performOnCell(0, cell => {
-    return cell.node.querySelector(".newtab-title").style.backgroundColor;
-  });
-
-  is(color, "green", "title bg color is green");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_background_captures.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Verifies that hidden, pre-loaded newtabs don't allow background captures, and
- * when unhidden, do allow background captures.
- */
-
-const CAPTURE_PREF = "browser.pagethumbnails.capturing_disabled";
-
-XPCOMUtils.defineLazyServiceGetter(this, "PageThumbsStorageService",
-  "@mozilla.org/thumbnails/pagethumbs-service;1",
-  "nsIPageThumbsStorageService");
-
-add_task(async function() {
-  // Disable captures.
-  await pushPrefs([CAPTURE_PREF, false]);
-
-  // Make sure the thumbnail doesn't exist yet.
-  let url = "http://example.com/";
-  let path = PageThumbsStorageService.getFilePathForURL(url);
-  let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
-  file.initWithPath(path);
-  try {
-    file.remove(false);
-  } catch (err) {}
-
-  // Add a top site.
-  await setLinks("-1");
-
-  // We need a handle to a hidden, pre-loaded newtab so we can verify that it
-  // doesn't allow background captures. Ensure we have a preloaded browser.
-  gBrowser._createPreloadBrowser();
-
-  // Wait for the preloaded browser to load.
-  if (gBrowser._preloadedBrowser.contentDocument.readyState != "complete") {
-    await BrowserTestUtils.waitForEvent(gBrowser._preloadedBrowser, "load", true);
-  }
-
-  // We're now ready to use the preloaded browser.
-  BrowserOpenTab();
-  let tab = gBrowser.selectedTab;
-
-  let thumbnailCreatedPromise = new Promise(resolve => {
-    // Showing the preloaded tab should trigger thumbnail capture.
-    Services.obs.addObserver(function onCreate(subj, topic, data) {
-      if (data != url)
-        return;
-      Services.obs.removeObserver(onCreate, "page-thumbnail:create");
-      ok(true, "thumbnail created after preloaded tab was shown");
-
-      resolve();
-    }, "page-thumbnail:create");
-  });
-
-  // Enable captures.
-  await pushPrefs([CAPTURE_PREF, false]);
-
-  await thumbnailCreatedPromise;
-
-  // Test finished!
-  gBrowser.removeTab(tab);
-  file.remove(false);
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_block.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-requestLongerTimeout(2);
-
-/*
- * These tests make sure that blocking/removing sites from the grid works
- * as expected. Pinned tabs should not be moved. Gaps will be re-filled
- * if more sites are available.
- */
-
-add_task(async function() {
-  // we remove sites and expect the gaps to be filled as long as there still
-  // are some sites available
-  await setLinks("0,1,2,3,4,5,6,7,8,9");
-  setPinnedLinks("");
-
-  await addNewTabPageTab();
-  await customizeNewTabPage("enhanced"); // Toggle enhanced off
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  await blockCell(4);
-  await checkGrid("0,1,2,3,5,6,7,8,9");
-
-  await blockCell(4);
-  await checkGrid("0,1,2,3,6,7,8,9,");
-
-  await blockCell(4);
-  await checkGrid("0,1,2,3,7,8,9,,");
-
-  // we removed a pinned site
-  await restore();
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",1");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1p,2,3,4,5,6,7,8");
-
-  await blockCell(1);
-  await checkGrid("0,2,3,4,5,6,7,8,");
-
-  // we remove the last site on the grid (which is pinned) and expect the gap
-  // to be re-filled and the new site to be unpinned
-  await restore();
-  await setLinks("0,1,2,3,4,5,6,7,8,9");
-  setPinnedLinks(",,,,,,,,8");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7,8p");
-
-  await blockCell(8);
-  await checkGrid("0,1,2,3,4,5,6,7,9");
-
-  // we remove the first site on the grid with the last one pinned. all cells
-  // but the last one should shift to the left and a new site fades in
-  await restore();
-  await setLinks("0,1,2,3,4,5,6,7,8,9");
-  setPinnedLinks(",,,,,,,,8");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7,8p");
-
-  await blockCell(0);
-  await checkGrid("1,2,3,4,5,6,7,9,8p");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug1271075.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  is(gBrowser.tabs.length, 1, "one tab is open initially");
-
-  // Add a few tabs.
-  let tabs = [];
-  function addTab(aURL, aReferrer) {
-    let tab = BrowserTestUtils.addTab(gBrowser, aURL, {referrerURI: aReferrer});
-    tabs.push(tab);
-    return BrowserTestUtils.browserLoaded(tab.linkedBrowser);
-  }
-
-  await addTab("http://mochi.test:8888/#0");
-  await addTab("http://mochi.test:8888/#1");
-  await addTab("http://mochi.test:8888/#2");
-  await addTab("http://mochi.test:8888/#3");
-
-  // Create a new tab page with a "www.example.com" tile and move it to the 2nd tab position.
-  await setLinks("-1");
-  await addNewTabPageTab();
-  gBrowser.moveTabTo(gBrowser.selectedTab, 1);
-
-  // Send a middle-click and confirm that the clicked site opens immediately next to the new tab page.
-  await BrowserTestUtils.synthesizeMouseAtCenter(".newtab-cell",
-                                                 {button: 1}, gBrowser.selectedBrowser);
-
-  await BrowserTestUtils.browserLoaded(gBrowser.getBrowserAtIndex(2));
-  is(gBrowser.getBrowserAtIndex(2).currentURI.spec, "http://example.com/",
-     "Middle click opens site in a new tab immediately to the right.");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug721442.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks([
-    {url: "http://example7.com/", title: ""},
-    {url: "http://example8.com/", title: "title"},
-    {url: "http://example9.com/", title: "http://example9.com/"}
-  ]);
-
-  await addNewTabPageTab();
-  await checkGrid("7p,8p,9p,0,1,2,3,4,5");
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    function checkTooltip(aIndex, aExpected, aMessage) {
-      let cell = content.gGrid.cells[aIndex];
-
-      let link = cell.node.querySelector(".newtab-link");
-      Assert.equal(link.getAttribute("title"), aExpected, aMessage);
-    }
-
-    checkTooltip(0, "http://example7.com/", "1st tooltip is correct");
-    checkTooltip(1, "title\nhttp://example8.com/", "2nd tooltip is correct");
-    checkTooltip(2, "http://example9.com/", "3rd tooltip is correct");
-  });
-});
-
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug722273.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const NOW = Date.now() * 1000;
-const URL = "http://fake-site.com/";
-
-add_task(async function() {
-  await Sanitizer.sanitize(["history"]);
-  await promiseAddFakeVisits();
-  await addNewTabPageTab();
-
-  let cellUrl = await performOnCell(0, cell => { return cell.site.url; });
-  is(cellUrl, URL, "first site is our fake site");
-
-  let updatedPromise = whenPagesUpdated();
-  await Sanitizer.sanitize(["history"]);
-  await updatedPromise;
-
-  let isGone = await performOnCell(0, cell => { return cell.site == null; });
-  ok(isGone, "fake site is gone");
-});
-
-function promiseAddFakeVisits() {
-  let visits = [];
-  for (let i = 59; i > 0; i--) {
-    visits.push({
-      visitDate: NOW - i * 60 * 1000000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK
-    });
-  }
-  let place = {
-    uri: makeURI(URL),
-    title: "fake site",
-    visits
-  };
-  return new Promise((resolve, reject) => {
-    PlacesUtils.asyncHistory.updatePlaces(place, {
-      handleError: () => reject(new Error("Couldn't add visit")),
-      handleResult() {},
-      handleCompletion() {
-        NewTabUtils.links.populateCache(function() {
-          NewTabUtils.allPages.update();
-          resolve();
-        }, true);
-      }
-    });
-  });
-}
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug723102.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  // create a new tab page and hide it.
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  await addNewTabPageTab();
-  let firstTab = gBrowser.selectedTab;
-
-  await addNewTabPageTab();
-  await BrowserTestUtils.removeTab(firstTab);
-
-  ok(NewTabUtils.allPages.enabled, "page is enabled");
-  NewTabUtils.allPages.enabled = false;
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
-    Assert.ok(content.gGrid.node.hasAttribute("page-disabled"), "page is disabled");
-  });
-
-  NewTabUtils.allPages.enabled = true;
-});
-
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug723121.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() {
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  await addNewTabPageTab();
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    let grid = content.gGrid;
-    let cell = grid.cells[0];
-    let site = cell.site.node;
-    let link = site.querySelector(".newtab-link");
-
-    function checkGridLocked(aLocked, aMessage) {
-      Assert.equal(grid.node.hasAttribute("locked"), aLocked, aMessage);
-    }
-
-    function sendDragEvent(aEventType, aTarget) {
-      let dataTransfer = new content.DataTransfer(aEventType, false);
-      let event = content.document.createEvent("DragEvent");
-      event.initDragEvent(aEventType, true, true, content, 0, 0, 0, 0, 0,
-                          false, false, false, false, 0, null, dataTransfer);
-      aTarget.dispatchEvent(event);
-    }
-
-    checkGridLocked(false, "grid is unlocked");
-
-    sendDragEvent("dragstart", link);
-    checkGridLocked(true, "grid is now locked");
-
-    sendDragEvent("dragend", link);
-    checkGridLocked(false, "grid isn't locked anymore");
-
-    sendDragEvent("dragstart", cell.node);
-    checkGridLocked(false, "grid isn't locked - dragstart was ignored");
-
-    sendDragEvent("dragstart", site);
-    checkGridLocked(false, "grid isn't locked - dragstart was ignored");
-  });
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug725996.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  function doDrop(data) {
-    return ContentTask.spawn(gBrowser.selectedBrowser, { data }, async function(args) {
-      let dataTransfer = new content.DataTransfer("dragstart", false);
-      dataTransfer.mozSetDataAt("text/x-moz-url", args.data, 0);
-      let event = content.document.createEvent("DragEvent");
-      event.initDragEvent("drop", true, true, content, 0, 0, 0, 0, 0,
-                          false, false, false, false, 0, null, dataTransfer);
-
-      let target = content.gGrid.cells[0].node;
-      target.dispatchEvent(event);
-    });
-  }
-
-  await doDrop("http://example99.com/\nblank");
-  is(NewTabUtils.pinnedLinks.links[0].url, "http://example99.com/",
-     "first cell is pinned and contains the dropped site");
-
-  await whenPagesUpdated();
-  await checkGrid("99p,0,1,2,3,4,5,6,7");
-
-  await doDrop("");
-  is(NewTabUtils.pinnedLinks.links[0].url, "http://example99.com/",
-     "first cell is still pinned with the site we dropped before");
-});
-
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug734043.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    content.addEventListener("error", function() {
-      sendAsyncMessage("test:newtab-error", {});
-    });
-  });
-
-  let receivedError = false;
-  let mm = gBrowser.selectedBrowser.messageManager;
-  mm.addMessageListener("test:newtab-error", function onResponse(message) {
-    mm.removeMessageListener("test:newtab-error", onResponse);
-    ok(false, "Error event happened");
-    receivedError = true;
-  });
-
-  let pagesUpdatedPromise = whenPagesUpdated();
-
-  for (let i = 0; i < 3; i++) {
-    await BrowserTestUtils.synthesizeMouseAtCenter(".newtab-control-block", {}, gBrowser.selectedBrowser);
-  }
-
-  await pagesUpdatedPromise;
-
-  ok(!receivedError, "we got here without any errors");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug735987.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  await simulateExternalDrop(1);
-  await checkGrid("0,99p,1,2,3,4,5,6,7");
-
-  await blockCell(1);
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  await simulateExternalDrop(1);
-  await checkGrid("0,99p,1,2,3,4,5,6,7");
-
-  // Simulate a restart and force the next about:newtab
-  // instance to read its data from the storage again.
-  NewTabUtils.blockedLinks.resetCache();
-
-  // Update all open pages, e.g. preloaded ones.
-  NewTabUtils.allPages.update();
-
-  await addNewTabPageTab();
-  await checkGrid("0,99p,1,2,3,4,5,6,7");
-
-  await blockCell(1);
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug752841.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const PREF_NEWTAB_ROWS = "browser.newtabpage.rows";
-const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns";
-
-function getCellsCount() {
-  return ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    return content.gGrid.cells.length;
-  });
-}
-
-add_task(async function() {
-  let testValues = [
-    {row: 0, column: 0},
-    {row: -1, column: -1},
-    {row: -1, column: 0},
-    {row: 0, column: -1},
-    {row: 2, column: 4},
-    {row: 2, column: 5},
-  ];
-
-  // Expected length of grid
-  let expectedValues = [1, 1, 1, 1, 8, 10];
-
-   // Values before setting new pref values (15 is the default value -> 5 x 3)
-  let previousValues = [15, 1, 1, 1, 1, 8];
-
-  await addNewTabPageTab();
-  let existingTab = gBrowser.selectedTab;
-
-  for (let i = 0; i < expectedValues.length; i++) {
-    let existingTabGridLength = await getCellsCount();
-    is(existingTabGridLength, previousValues[i],
-      "Grid length of existing page before update is correctly.");
-
-    await pushPrefs([PREF_NEWTAB_ROWS, testValues[i].row]);
-    await pushPrefs([PREF_NEWTAB_COLUMNS, testValues[i].column]);
-
-    existingTabGridLength = await getCellsCount();
-    is(existingTabGridLength, expectedValues[i],
-      "Existing page grid is updated correctly.");
-
-    await addNewTabPageTab();
-    let newTab = gBrowser.selectedTab;
-    let newTabGridLength = await getCellsCount();
-    is(newTabGridLength, expectedValues[i],
-      "New page grid is updated correctly.");
-
-    await BrowserTestUtils.removeTab(newTab);
-  }
-
-  gBrowser.removeTab(existingTab);
-});
-
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug765628.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    const BAD_DRAG_DATA = "javascript:alert('h4ck0rz');\nbad stuff";
-    const GOOD_DRAG_DATA = "http://example99.com/\nsite 99";
-
-    function sendDropEvent(aCellIndex, aDragData) {
-      let dataTransfer = new content.DataTransfer("dragstart", false);
-      dataTransfer.mozSetDataAt("text/x-moz-url", aDragData, 0);
-      let event = content.document.createEvent("DragEvent");
-      event.initDragEvent("drop", true, true, content, 0, 0, 0, 0, 0,
-                          false, false, false, false, 0, null, dataTransfer);
-
-      let target = content.gGrid.cells[aCellIndex].node;
-      target.dispatchEvent(event);
-    }
-
-    sendDropEvent(0, BAD_DRAG_DATA);
-    sendDropEvent(1, GOOD_DRAG_DATA);
-  });
-
-  await whenPagesUpdated();
-  await checkGrid("0,99p,1,2,3,4,5,6,7");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug876313.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * This test makes sure that the changes made by unpinning
- * a site are actually written to NewTabUtils' storage.
- */
-add_task(async function() {
-  // Second cell is pinned with page #99.
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",99");
-
-  await addNewTabPageTab();
-  await checkGrid("0,99p,1,2,3,4,5,6,7");
-
-  // Unpin the second cell's site.
-  await unpinCell(1);
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  // Clear the pinned cache to force NewTabUtils to read the pref again.
-  NewTabUtils.pinnedLinks.resetCache();
-  NewTabUtils.allPages.update();
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug991111.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  // set max rows to 1, to avoid scroll events by clicking middle button
-  await pushPrefs(["browser.newtabpage.rows", 1]);
-  await setLinks("-1");
-  await addNewTabPageTab();
-  // we need a second newtab to honor max rows
-  await addNewTabPageTab();
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, {index: 0}, async function(args) {
-    let {site} = content.wrappedJSObject.gGrid.cells[args.index];
-
-    let origOnClick = site.onClick;
-    site.onClick = e => {
-      origOnClick.call(site, e);
-      sendAsyncMessage("test:clicked-on-cell", {});
-    };
-  });
-
-  let mm = gBrowser.selectedBrowser.messageManager;
-  let messagePromise = new Promise(resolve => {
-    mm.addMessageListener("test:clicked-on-cell", function onResponse(message) {
-      mm.removeMessageListener("test:clicked-on-cell", onResponse);
-      resolve();
-    });
-  });
-
-  // Send a middle-click and make sure it happened
-  await BrowserTestUtils.synthesizeMouseAtCenter(".newtab-cell",
-                                                 {button: 1}, gBrowser.selectedBrowser);
-  await messagePromise;
-  ok(true, "middle click triggered click listener");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug991210.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  // turn off preload to ensure that a newtab page loads
-  await pushPrefs(["browser.newtab.preload", false]);
-
-  // add a test provider that waits for load
-  let afterLoadProvider = {
-    getLinks(callback) {
-      this.callback = callback;
-    },
-    addObserver() {},
-  };
-  NewTabUtils.links.addProvider(afterLoadProvider);
-
-  // wait until about:newtab loads before calling provider callback
-  await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab");
-
-  afterLoadProvider.callback([]);
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    let {_cellHeight, _cellWidth, node} = content.gGrid;
-    Assert.notEqual(_cellHeight, null, "grid has a computed cell height");
-    Assert.notEqual(_cellWidth, null, "grid has a computed cell width");
-    let {height, maxHeight, maxWidth} = node.style;
-    Assert.notEqual(height, "", "grid has a computed grid height");
-    Assert.notEqual(maxHeight, "", "grid has a computed grid max-height");
-    Assert.notEqual(maxWidth, "", "grid has a computed grid max-width");
-  });
-
-  // restore original state
-  NewTabUtils.links.removeProvider(afterLoadProvider);
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_bug998387.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-add_task(async function() {
-  // set max rows to 1, to avoid scroll events by clicking middle button
-  await pushPrefs(["browser.newtabpage.rows", 1]);
-  await setLinks("0");
-  await addNewTabPageTab();
-  // we need a second newtab to honor max rows
-  await addNewTabPageTab();
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, {index: 0}, async function(args) {
-    let {site} = content.wrappedJSObject.gGrid.cells[args.index];
-
-    let origOnClick = site.onClick;
-    site.onClick = e => {
-      origOnClick.call(site, e);
-      sendAsyncMessage("test:clicked-on-cell", {});
-    };
-  });
-
-  let mm = gBrowser.selectedBrowser.messageManager;
-  let messagePromise = new Promise(resolve => {
-    mm.addMessageListener("test:clicked-on-cell", function onResponse(message) {
-      mm.removeMessageListener("test:clicked-on-cell", onResponse);
-      resolve();
-    });
-  });
-
-  // Send a middle-click and make sure it happened
-  await BrowserTestUtils.synthesizeMouseAtCenter(".newtab-control-block",
-                                                 {button: 1}, gBrowser.selectedBrowser);
-
-  await messagePromise;
-  ok(true, "middle click triggered click listener");
-
-  // Make sure the cell didn't actually get blocked
-  await checkGrid("0");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_disable.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * These tests make sure that the 'New Tab Page' feature can be disabled if the
- * decides not to use it.
- */
-add_task(async function() {
-  // create a new tab page and hide it.
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  let firstTab = await addNewTabPageTab();
-
-  function isGridDisabled(browser = gBrowser.selectedBrowser) {
-    return ContentTask.spawn(browser, {}, async function() {
-      return content.gGrid.node.hasAttribute("page-disabled");
-    });
-  }
-
-  let isDisabled = await isGridDisabled();
-  ok(!isDisabled, "page is not disabled");
-
-  NewTabUtils.allPages.enabled = false;
-
-  isDisabled = await isGridDisabled();
-  ok(isDisabled, "page is disabled");
-
-  // create a second new tab page and make sure it's disabled. enable it
-  // again and check if the former page gets enabled as well.
-  await addNewTabPageTab();
-  isDisabled = await isGridDisabled(firstTab.linkedBrowser);
-  ok(isDisabled, "page is disabled");
-
-  // check that no sites have been rendered
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    Assert.equal(content.document.querySelectorAll(".site").length, 0,
-      "no sites have been rendered");
-  });
-
-  NewTabUtils.allPages.enabled = true;
-
-  isDisabled = await isGridDisabled();
-  ok(!isDisabled, "page is not disabled");
-
-  isDisabled = await isGridDisabled(firstTab.linkedBrowser);
-  ok(!isDisabled, "old page is not disabled");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_drag_drop.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * These tests make sure that dragging and dropping sites works as expected.
- * Sites contained in the grid need to shift around to indicate the result
- * of the drag-and-drop operation. If the grid is full and we're dragging
- * a new site into it another one gets pushed out.
- */
-add_task(async function() {
-  requestLongerTimeout(2);
-  await addNewTabPageTab();
-
-  // test a simple drag-and-drop scenario
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  await doDragEvent(0, 1);
-  await checkGrid("1,0p,2,3,4,5,6,7,8");
-
-  // drag a cell to its current cell and make sure it's not pinned afterwards
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  await doDragEvent(0, 0);
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  // ensure that pinned pages aren't moved if that's not necessary
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",1,2");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1p,2p,3,4,5,6,7,8");
-
-  await doDragEvent(0, 3);
-  await checkGrid("3,1p,2p,0p,4,5,6,7,8");
-
-  // pinned sites should always be moved around as blocks. if a pinned site is
-  // moved around, neighboring pinned are affected as well
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("0,1");
-
-  await addNewTabPageTab();
-  await checkGrid("0p,1p,2,3,4,5,6,7,8");
-
-  await doDragEvent(2, 0);
-  await checkGrid("2p,0p,1p,3,4,5,6,7,8");
-
-  // pinned sites should not be pushed out of the grid (unless there are only
-  // pinned ones left on the grid)
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",,,,,,,7,8");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7p,8p");
-
-  await doDragEvent(2, 5);
-  await checkGrid("0,1,3,4,5,2p,6,7p,8p");
-
-  // make sure that pinned sites are re-positioned correctly
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("0,1,2,,,5");
-
-  await addNewTabPageTab();
-  await checkGrid("0p,1p,2p,3,4,5p,6,7,8");
-
-  await doDragEvent(0, 4);
-  await checkGrid("3,1p,2p,4,0p,5p,6,7,8");
-});
-
-function doDragEvent(sourceIndex, dropIndex) {
-  return ContentTask.spawn(gBrowser.selectedBrowser,
-                           { sourceIndex, dropIndex }, async function(args) {
-    let dataTransfer = new content.DataTransfer("dragstart", false);
-    let event = content.document.createEvent("DragEvent");
-    event.initDragEvent("dragstart", true, true, content, 0, 0, 0, 0, 0,
-                        false, false, false, false, 0, null, dataTransfer);
-
-    let target = content.gGrid.cells[args.sourceIndex].site.node;
-    target.dispatchEvent(event);
-
-    event = content.document.createEvent("DragEvent");
-    event.initDragEvent("drop", true, true, content, 0, 0, 0, 0, 0,
-                        false, false, false, false, 0, null, dataTransfer);
-
-    target = content.gGrid.cells[args.dropIndex].node;
-    target.dispatchEvent(event);
-  });
-}
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_drag_drop_ext.js
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-requestLongerTimeout(2);
-
-const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns";
-const PREF_NEWTAB_ROWS = "browser.newtabpage.rows";
-
-/*
- * These tests make sure that dragging and dropping sites works as expected.
- * Sites contained in the grid need to shift around to indicate the result
- * of the drag-and-drop operation. If the grid is full and we're dragging
- * a new site into it another one gets pushed out.
- * This is a continuation of browser_newtab_drag_drop.js
- * to decrease test run time, focusing on external sites.
- */
- add_task(async function() {
-  await addNewTabPageTab();
-
-  // drag a new site onto the very first cell
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",,,,,,,7,8");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7p,8p");
-
-  await simulateExternalDrop(0);
-  await checkGrid("99p,0,1,2,3,4,5,7p,8p");
-
-  // drag a new site onto the grid and make sure that pinned cells don't get
-  // pushed out
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",,,,,,,7,8");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7p,8p");
-
-  // force the grid to be small enough that a pinned cell could be pushed out
-  await pushPrefs([PREF_NEWTAB_COLUMNS, 3]);
-  await pushPrefs([PREF_NEWTAB_ROWS, 3]);
-  await simulateExternalDrop(5);
-  await checkGrid("0,1,2,3,4,99p,5,7p,8p");
-
-  // drag a new site beneath a pinned cell and make sure the pinned cell is
-  // not moved
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",,,,,,,,8");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1,2,3,4,5,6,7,8p");
-
-  await simulateExternalDrop(5);
-  await checkGrid("0,1,2,3,4,99p,5,6,8p");
-
-  // drag a new site onto a block of pinned sites and make sure they're shifted
-  // around accordingly
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("0,1,2,,,,,,");
-
-  await addNewTabPageTab();
-  await checkGrid("0p,1p,2p");
-
-  await simulateExternalDrop(1);
-  await checkGrid("0p,99p,1p,2p,3,4,5,6,7");
-
-  // force the grid to be small enough that a pinned cell could be pushed out
-  // and the full list is truncated
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",,,,,,,7,8");
-
-  await addNewTabPageTab();
-  await pushPrefs([PREF_NEWTAB_ROWS, 2]);
-  await simulateExternalDrop(5);
-  await checkGrid("0,1,2,3,4,99p");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_drop_preview.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * These tests ensure that the drop preview correctly arranges sites when
- * dragging them around.
- */
-add_task(async function() {
-  await addNewTabPageTab();
-
-  // the first three sites are pinned - make sure they're re-arranged correctly
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("0,1,2,,,5");
-
-  await addNewTabPageTab();
-  await checkGrid("0p,1p,2p,3,4,5p,6,7,8");
-
-  let foundSites = await ContentTask.spawn(gWindow.gBrowser.selectedBrowser, {}, async function() {
-    let cells = content.gGrid.cells;
-    content.gDrag._draggedSite = cells[0].site;
-    let sites = content.gDropPreview.rearrange(cells[4]);
-    content.gDrag._draggedSite = null;
-
-    sites = sites.slice(0, 9);
-    return sites.map(function(aSite) {
-      if (!aSite)
-        return "";
-
-      let pinned = aSite.isPinned();
-      if (pinned != aSite.node.hasAttribute("pinned")) {
-        Assert.ok(false, "invalid state (site.isPinned() != site[pinned])");
-      }
-
-      return aSite.url.replace(/^http:\/\/example(\d+)\.com\/$/, "$1") + (pinned ? "p" : "");
-    });
-  });
-
-  let expectedSites = "3,1p,2p,4,0p,5p,6,7,8";
-  is(foundSites, expectedSites, "grid status = " + expectedSites);
-});
-
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_focus.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * These tests make sure that focusing the 'New Tab Page' works as expected.
- */
-add_task(async function() {
-  await pushPrefs(["accessibility.tabfocus", 7]);
-
-  // When the onboarding component is enabled, it would inject extra tour notification into
-  // the newtab page so there would be 3 more overlay button, notification close button and action button
-  let onbardingEnabled = Services.prefs.getBoolPref("browser.onboarding.enabled");
-
-  // Focus count in new tab page.
-  // 30 = 9 * 3 + 3 = 9 sites, each with link, pin and remove buttons; search
-  // bar; search button; and toggle button. Additionaly there may or may not be
-  // a scroll bar caused by fix to 1180387, which will eat an extra focus
-  let FOCUS_COUNT = 30;
-
-  // Create a new tab page.
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("");
-
-  if (onbardingEnabled) {
-    await promiseNoMuteNotificationOnFirstSession();
-  }
-  let tab = await addNewTabPageTab();
-  if (onbardingEnabled) {
-    FOCUS_COUNT += 3;
-    await promiseTourNotificationOpened(tab.linkedBrowser);
-  }
-  gURLBar.focus();
-  // Count the focus with the enabled page.
-  countFocus(FOCUS_COUNT);
-  // Disable page and count the focus with the disabled page.
-  NewTabUtils.allPages.enabled = false;
-
-  let expectedCount = 4;
-  if (onbardingEnabled) {
-    expectedCount += 3;
-  }
-  countFocus(expectedCount);
-
-  NewTabUtils.allPages.enabled = true;
-});
-
-/**
- * Focus the urlbar and count how many focus stops to return again to the urlbar.
- */
-function countFocus(aExpectedCount) {
-  let focusCount = 0;
-  do {
-    EventUtils.synthesizeKey("KEY_Tab");
-    if (document.activeElement == gBrowser.selectedBrowser) {
-      focusCount++;
-    }
-  } while (document.activeElement != gURLBar.inputField);
-  ok(focusCount == aExpectedCount || focusCount == (aExpectedCount + 1),
-     "Validate focus count in the new tab page.");
-}
-
-function promiseNoMuteNotificationOnFirstSession() {
-  return SpecialPowers.pushPrefEnv({set: [["browser.onboarding.notification.mute-duration-on-first-session-ms", 0]]});
-}
-
-/**
- * Wait for the onboarding tour notification opens
- */
-function promiseTourNotificationOpened(browser) {
-  return ContentTask.spawn(browser, {}, function() {
-    let doc = content && content.document;
-    let notification = doc.querySelector("#onboarding-notification-bar");
-    if (notification && notification.classList.contains("onboarding-opened")) {
-      ok(true, "Should open tour notification");
-      return Promise.resolve();
-    }
-    return new Promise(resolve => {
-      let observer = new content.MutationObserver(mutations => {
-        mutations.forEach(mutation => {
-          let bar = Array.from(mutation.addedNodes)
-                         .find(node => node.id == "onboarding-notification-bar");
-          if (bar && bar.classList.contains("onboarding-opened")) {
-            observer.disconnect();
-            ok(true, "Should open tour notification");
-            resolve();
-          }
-        });
-      });
-      observer.observe(doc.body, { childList: true });
-    });
-  });
-}
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_fullscreen_focus.js
+++ /dev/null
@@ -1,35 +0,0 @@
-"use strict";
-
-function isFullscreenSizeMode() {
-  let sizemode = document.documentElement.getAttribute("sizemode");
-  return sizemode == "fullscreen";
-}
-
-/**
- * Checks that the URL bar is correctly focused
- * when a new tab is opened while in fullscreen
- * mode.
- */
-add_task(async function() {
-  gURLBar.blur();
-
-  Assert.ok(!window.fullScreen, "Should not start in fullscreen mode.");
-  BrowserFullScreen();
-  await BrowserTestUtils.waitForCondition(() => isFullscreenSizeMode());
-
-  registerCleanupFunction(async function() {
-    // Exit fullscreen if we're still in it.
-    if (window.fullScreen) {
-      BrowserFullScreen();
-      await BrowserTestUtils.waitForCondition(() => !isFullscreenSizeMode());
-    }
-  });
-
-  Assert.ok(window.fullScreen, "Should be in fullscreen mode now.");
-
-  let newTabOpened = BrowserTestUtils.waitForEvent(gBrowser, "TabSwitchDone");
-  BrowserOpenTab();
-  await newTabOpened;
-
-  Assert.ok(gURLBar.focused, "URL bar should be focused.");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_perwindow_private_browsing.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * These tests ensure that all changes made to the new tab page in private
- * browsing mode are discarded after switching back to normal mode again.
- * The private browsing mode should start with the current grid shown in normal
- * mode.
- */
-
-add_task(async function() {
-  // prepare the grid
-  await testOnWindow(undefined);
-  await setLinks("0,1,2,3,4,5,6,7,8,9");
-
-  await addNewTabPageTab();
-  await pinCell(0);
-  await checkGrid("0p,1,2,3,4,5,6,7,8");
-
-  // open private window
-  await testOnWindow({private: true});
-
-  await addNewTabPageTab();
-  await checkGrid("0p,1,2,3,4,5,6,7,8");
-
-  // modify the grid while we're in pb mode
-  await blockCell(1);
-  await checkGrid("0p,2,3,4,5,6,7,8");
-
-  await unpinCell(0);
-  await checkGrid("0,2,3,4,5,6,7,8");
-
-  // open normal window
-  await testOnWindow(undefined);
-
-  // check that the grid is the same as before entering pb mode
-  await addNewTabPageTab();
-  await checkGrid("0,2,3,4,5,6,7,8");
-});
-
-var windowsToClose = [];
-async function testOnWindow(options) {
-  let newWindowPromise = BrowserTestUtils.waitForNewWindow();
-  var win = OpenBrowserWindow(options);
-  windowsToClose.push(win);
-  gWindow = win;
-  await newWindowPromise;
-}
-
-registerCleanupFunction(function() {
-  gWindow = window;
-  windowsToClose.forEach(function(win) {
-    win.close();
-  });
-});
-
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_reflow_load.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-/* eslint-disable mozilla/no-arbitrary-setTimeout */
-
-"use strict";
-
-const FRAME_SCRIPT = getRootDirectory(gTestPath) + "content-reflows.js";
-const ADDITIONAL_WAIT_MS = 2000;
-
-/*
- * Ensure that loading about:newtab doesn't cause uninterruptible reflows.
- */
-add_task(async function() {
-  await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
-    return gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:blank", {animate: false});
-  }, false);
-
-  let browser = gBrowser.selectedBrowser;
-  let mm = browser.messageManager;
-  mm.loadFrameScript(FRAME_SCRIPT, true);
-  mm.addMessageListener("newtab-reflow", ({data: stack}) => {
-    ok(false, `unexpected uninterruptible reflow ${stack}`);
-  });
-
-  let browserLoadedPromise = BrowserTestUtils.waitForEvent(browser, "load", true);
-  browser.loadURI("about:newtab");
-  await browserLoadedPromise;
-
-  // Wait some more to catch sync reflows after the page has loaded.
-  await new Promise(resolve => {
-    setTimeout(resolve, ADDITIONAL_WAIT_MS);
-  });
-
-  // Clean up.
-  gBrowser.removeCurrentTab({animate: false});
-
-  ok(true, "Each test requires at least one pass, fail or todo so here is a pass.");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_search.js
+++ /dev/null
@@ -1,240 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// See browser/components/search/test/browser_*_behavior.js for tests of actual
-// searches.
-
-
-const ENGINE_NO_LOGO = {
-  name: "searchEngineNoLogo.xml",
-  numLogos: 0,
-};
-
-const ENGINE_FAVICON = {
-  name: "searchEngineFavicon.xml",
-  logoPrefix1x: "data:image/png;base64,AAABAAIAICAAAAEAIACoEAAAJgAAABAQAAABACAAaAQAAM4QAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAATCwAAEwsA",
-  numLogos: 1,
-};
-ENGINE_FAVICON.logoPrefix2x = ENGINE_FAVICON.logoPrefix1x;
-
-const ENGINE_1X_LOGO = {
-  name: "searchEngine1xLogo.xml",
-  logoPrefix1x: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAaCAIAAABn3KYmAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADEw",
-  numLogos: 1,
-};
-ENGINE_1X_LOGO.logoPrefix2x = ENGINE_1X_LOGO.logoPrefix1x;
-
-const ENGINE_2X_LOGO = {
-  name: "searchEngine2xLogo.xml",
-  logoPrefix2x: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAA0CAIAAADJ8nfCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADMU",
-  numLogos: 1,
-};
-ENGINE_2X_LOGO.logoPrefix1x = ENGINE_2X_LOGO.logoPrefix2x;
-
-const ENGINE_1X_2X_LOGO = {
-  name: "searchEngine1x2xLogo.xml",
-  logoPrefix1x: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAaCAIAAABn3KYmAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADIG",
-  logoPrefix2x: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAA0CAIAAADJ8nfCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADMo",
-  numLogos: 2,
-};
-
-const ENGINE_SUGGESTIONS = {
-  name: "searchSuggestionEngine.xml",
-  numLogos: 0,
-};
-
-// The test has an expected search event queue and a search event listener.
-// Search events that are expected to happen are added to the queue, and the
-// listener consumes the queue and ensures that each event it receives is at
-// the head of the queue.
-let gExpectedSearchEventQueue = [];
-let gExpectedSearchEventResolver = null;
-
-let gNewEngines = [];
-
-add_task(async function() {
-  let oldCurrentEngine = Services.search.currentEngine;
-
-  await addNewTabPageTab();
-
-  // The tab is removed at the end of the test, so there's no need to remove
-  // this listener at the end of the test.
-  info("Adding search event listener");
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    const SERVICE_EVENT_NAME = "ContentSearchService";
-    content.addEventListener(SERVICE_EVENT_NAME, function(event) {
-      sendAsyncMessage("test:search-event", { eventType: event.detail.type });
-    });
-  });
-
-  let mm = gBrowser.selectedBrowser.messageManager;
-  mm.addMessageListener("test:search-event", function(message) {
-    let eventType = message.data.eventType;
-    if (!gExpectedSearchEventResolver) {
-      ok(false, "Got search event " + eventType + " with no promise assigned");
-    }
-
-    let expectedEventType = gExpectedSearchEventQueue.shift();
-    is(eventType, expectedEventType, "Got expected search event " + expectedEventType);
-    if (!gExpectedSearchEventQueue.length) {
-      gExpectedSearchEventResolver();
-      gExpectedSearchEventResolver = null;
-    }
-  });
-
-  // Add the engine without any logos and switch to it.
-  let noLogoEngine = await promiseNewSearchEngine(ENGINE_NO_LOGO);
-  let searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
-  Services.search.currentEngine = noLogoEngine;
-  await searchEventsPromise;
-  await checkCurrentEngine(ENGINE_NO_LOGO);
-
-  // Add the engine with favicon and switch to it.
-  let faviconEngine = await promiseNewSearchEngine(ENGINE_FAVICON);
-  searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
-  Services.search.currentEngine = faviconEngine;
-  await searchEventsPromise;
-  await checkCurrentEngine(ENGINE_FAVICON);
-
-  // Add the engine with a 1x-DPI logo and switch to it.
-  let logo1xEngine = await promiseNewSearchEngine(ENGINE_1X_LOGO);
-  searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
-  Services.search.currentEngine = logo1xEngine;
-  await searchEventsPromise;
-  await checkCurrentEngine(ENGINE_1X_LOGO);
-
-  // Add the engine with a 2x-DPI logo and switch to it.
-  let logo2xEngine = await promiseNewSearchEngine(ENGINE_2X_LOGO);
-  searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
-  Services.search.currentEngine = logo2xEngine;
-  await searchEventsPromise;
-  await checkCurrentEngine(ENGINE_2X_LOGO);
-
-  // Add the engine with 1x- and 2x-DPI logos and switch to it.
-  let logo1x2xEngine = await promiseNewSearchEngine(ENGINE_1X_2X_LOGO);
-  searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
-  Services.search.currentEngine = logo1x2xEngine;
-  await searchEventsPromise;
-  await checkCurrentEngine(ENGINE_1X_2X_LOGO);
-
-  // Add the engine that provides search suggestions and switch to it.
-  let suggestionEngine = await promiseNewSearchEngine(ENGINE_SUGGESTIONS);
-  searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
-  Services.search.currentEngine = suggestionEngine;
-  await searchEventsPromise;
-  await checkCurrentEngine(ENGINE_SUGGESTIONS);
-
-  // Type an X in the search input.  This is only a smoke test.  See
-  // browser_searchSuggestionUI.js for comprehensive content search suggestion
-  // UI tests.
-  let suggestionsOpenPromise = new Promise(resolve => {
-    mm.addMessageListener("test:newtab-suggestions-open", function onResponse(message) {
-      mm.removeMessageListener("test:newtab-suggestions-open", onResponse);
-      resolve();
-    });
-  });
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    let table = content.document.getElementById("searchSuggestionTable");
-
-    let input = content.document.getElementById("newtab-search-text");
-    input.focus();
-
-    info("Waiting for suggestions table to open");
-    let observer = new content.MutationObserver(() => {
-      if (input.getAttribute("aria-expanded") == "true") {
-        observer.disconnect();
-        Assert.ok(!table.hidden, "Search suggestion table unhidden");
-        sendAsyncMessage("test:newtab-suggestions-open", {});
-      }
-    });
-    observer.observe(input, {
-      attributes: true,
-      attributeFilter: ["aria-expanded"],
-    });
-  });
-
-  let suggestionsPromise = promiseSearchEvents(["Suggestions"]);
-
-  EventUtils.sendString("x");
-
-  // Wait for the search suggestions to become visible and for the Suggestions
-  // message.
-  await suggestionsOpenPromise;
-  await suggestionsPromise;
-
-  // Empty the search input, causing the suggestions to be hidden.
-  EventUtils.synthesizeKey("a", {accelKey: true});
-  EventUtils.synthesizeKey("KEY_Delete");
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-    Assert.ok(content.document.getElementById("searchSuggestionTable").hidden,
-      "Search suggestion table hidden");
-  });
-
-  // Done.  Revert the current engine and remove the new engines.
-  searchEventsPromise = promiseSearchEvents(["CurrentEngine"]);
-  Services.search.currentEngine = oldCurrentEngine;
-  await searchEventsPromise;
-
-  let events = Array(gNewEngines.length).fill("CurrentState", 0, gNewEngines.length);
-  searchEventsPromise = promiseSearchEvents(events);
-
-  for (let engine of gNewEngines) {
-    Services.search.removeEngine(engine);
-  }
-  await searchEventsPromise;
-});
-
-function promiseSearchEvents(events) {
-  info("Expecting search events: " + events);
-  return new Promise(resolve => {
-    gExpectedSearchEventQueue.push(...events);
-    gExpectedSearchEventResolver = resolve;
-  });
-}
-
-function promiseNewSearchEngine({name: basename, numLogos}) {
-  info("Waiting for engine to be added: " + basename);
-
-  // Wait for the search events triggered by adding the new engine.
-  // engine-added engine-loaded
-  let expectedSearchEvents = ["CurrentState", "CurrentState"];
-  // engine-changed for each of the logos
-  for (let i = 0; i < numLogos; i++) {
-    expectedSearchEvents.push("CurrentState");
-  }
-  let eventPromise = promiseSearchEvents(expectedSearchEvents);
-
-  // Wait for addEngine().
-  let addEnginePromise = new Promise((resolve, reject) => {
-    let url = getRootDirectory(gTestPath) + basename;
-    Services.search.addEngine(url, null, "", false, {
-      onSuccess(engine) {
-        info("Search engine added: " + basename);
-        gNewEngines.push(engine);
-        resolve(engine);
-      },
-      onError(errCode) {
-        ok(false, "addEngine failed with error code " + errCode);
-        reject();
-      },
-    });
-  });
-
-  return Promise.all([addEnginePromise, eventPromise]).then(([newEngine, _]) => {
-    return newEngine;
-  });
-}
-
-async function checkCurrentEngine(engineInfo) {
-  let engine = Services.search.currentEngine;
-  ok(engine.name.includes(engineInfo.name),
-     "Sanity check: current engine: engine.name=" + engine.name +
-     " basename=" + engineInfo.name);
-
-  await ContentTask.spawn(gBrowser.selectedBrowser, { name: engine.name }, async function(args) {
-    Assert.equal(content.gSearch._contentSearchController.defaultEngine.name,
-      args.name, "currentEngineName: " + args.name);
-  });
-}
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_undo.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * These tests make sure that the undo dialog works as expected.
- */
-add_task(async function() {
-  // remove unpinned sites and undo it
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks("5");
-
-  await addNewTabPageTab();
-  await checkGrid("5p,0,1,2,3,4,6,7,8");
-
-  await blockCell(4);
-  await blockCell(4);
-  await checkGrid("5p,0,1,2,6,7,8");
-
-  await undo();
-  await checkGrid("5p,0,1,2,4,6,7,8");
-
-  // now remove a pinned site and undo it
-  await blockCell(0);
-  await checkGrid("0,1,2,4,6,7,8");
-
-  await undo();
-  await checkGrid("5p,0,1,2,4,6,7,8");
-
-  // remove a site and restore all
-  await blockCell(1);
-  await checkGrid("5p,1,2,4,6,7,8");
-
-  await undoAll();
-  await checkGrid("5p,0,1,2,3,4,6,7,8");
-});
-
-async function undo() {
-  let updatedPromise = whenPagesUpdated();
-  await BrowserTestUtils.synthesizeMouseAtCenter("#newtab-undo-button", {}, gBrowser.selectedBrowser);
-  await updatedPromise;
-}
-
-async function undoAll() {
-  let updatedPromise = whenPagesUpdated();
-  await BrowserTestUtils.synthesizeMouseAtCenter("#newtab-undo-restore-button", {}, gBrowser.selectedBrowser);
-  await updatedPromise;
-}
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_unpin.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * These tests make sure that when a site gets unpinned it is either moved to
- * its actual place in the grid or removed in case it's not on the grid anymore.
- */
-add_task(async function() {
-  // we have a pinned link that didn't change its position since it was pinned.
-  // nothing should happen when we unpin it.
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",1");
-
-  await addNewTabPageTab();
-  await checkGrid("0,1p,2,3,4,5,6,7,8");
-
-  await unpinCell(1);
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  // we have a pinned link that is not anymore in the list of the most-visited
-  // links. this should disappear, the remaining links adjust their positions
-  // and a new link will appear at the end of the grid.
-  await setLinks("0,1,2,3,4,5,6,7,8");
-  setPinnedLinks(",99");
-
-  await addNewTabPageTab();
-  await checkGrid("0,99p,1,2,3,4,5,6,7");
-
-  await unpinCell(1);
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-
-  // we have a pinned link that changed its position since it was pinned. it
-  // should be moved to its new position after being unpinned.
-  await setLinks("0,1,2,3,4,5,6,7");
-  setPinnedLinks(",1,,,,,,,0");
-
-  await addNewTabPageTab();
-  await checkGrid("2,1p,3,4,5,6,7,,0p");
-
-  await unpinCell(1);
-  await checkGrid("1,2,3,4,5,6,7,,0p");
-
-  await unpinCell(8);
-  await checkGrid("0,1,2,3,4,5,6,7,");
-
-  // we have pinned link that changed its position since it was pinned. the
-  // link will disappear from the grid because it's now a much lower priority
-  await setLinks("0,1,2,3,4,5,6,7,8,9");
-  setPinnedLinks("9");
-
-  await addNewTabPageTab();
-  await checkGrid("9p,0,1,2,3,4,5,6,7");
-
-  await unpinCell(0);
-  await checkGrid("0,1,2,3,4,5,6,7,8");
-});
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_update.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-/**
- * Checks that newtab is updated as its links change.
- */
-add_task(async function() {
-  // First, start with an empty page.  setLinks will trigger a hidden page
-  // update because it calls clearHistory.  We need to wait for that update to
-  // happen so that the next time we wait for a page update below, we catch the
-  // right update and not the one triggered by setLinks.
-  let updatedPromise = whenPagesUpdated();
-  let setLinksPromise = setLinks([]);
-  await Promise.all([updatedPromise, setLinksPromise]);
-
-  // Strategy: Add some visits, open a new page, check the grid, repeat.
-  await fillHistoryAndWaitForPageUpdate([1]);
-  await addNewTabPageTab();
-  await checkGrid("1,,,,,,,,");
-
-  await fillHistoryAndWaitForPageUpdate([2]);
-  await addNewTabPageTab();
-  await checkGrid("2,1,,,,,,,");
-
-  await fillHistoryAndWaitForPageUpdate([1]);
-  await addNewTabPageTab();
-  await checkGrid("1,2,,,,,,,");
-
-  await fillHistoryAndWaitForPageUpdate([2, 3, 4]);
-  await addNewTabPageTab();
-  await checkGrid("2,1,3,4,,,,,");
-
-  // Make sure these added links have the right type
-  let type = await performOnCell(1, cell => { return cell.site.link.type; });
-  is(type, "history", "added link is history");
-});
-
-function fillHistoryAndWaitForPageUpdate(links) {
-  let updatedPromise = whenPagesUpdated;
-  let fillHistoryPromise = fillHistory(links.map(link));
-  return Promise.all([updatedPromise, fillHistoryPromise]);
-}
-
-function link(id) {
-  return { url: "http://example" + id + ".com/", title: "site#" + id };
-}
deleted file mode 100644
--- a/browser/base/content/test/newtab/content-reflows.js
+++ /dev/null
@@ -1,26 +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/. */
-
-/* eslint-env mozilla/frame-script */
-
-(function() {
-  "use strict";
-
-  docShell.addWeakReflowObserver({
-    reflow() {
-      // Gather information about the current code path.
-      let path = (new Error().stack).split("\n").slice(1).join("\n");
-      if (path) {
-        sendSyncMessage("newtab-reflow", path);
-      }
-    },
-
-    reflowInterruptible() {
-      // We're not interested in interruptible reflows.
-    },
-
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsIReflowObserver,
-                                           Ci.nsISupportsWeakReference])
-  });
-})();
deleted file mode 100644
--- a/browser/base/content/test/newtab/head.js
+++ /dev/null
@@ -1,526 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const PREF_NEWTAB_ENABLED = "browser.newtabpage.enabled";
-
-Services.prefs.setBoolPref(PREF_NEWTAB_ENABLED, true);
-
-// Opens and closes a new tab to clear any existing preloaded ones. This is
-// necessary to prevent any left-over activity-stream preloaded new tabs from
-// affecting these tests.
-BrowserOpenTab();
-const initialTab = gBrowser.selectedTab;
-gBrowser.removeTab(initialTab);
-
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetters(this, {
-  NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
-  PlacesTestUtils: "resource://testing-common/PlacesTestUtils.jsm",
-  Sanitizer: "resource:///modules/Sanitizer.jsm",
-});
-
-var gWindow = window;
-
-// Default to dummy/empty directory links
-var gDirectorySource = 'data:application/json,{"test":1}';
-var gOrigDirectorySource;
-
-// The tests assume all 3 rows and all 3 columns of sites are shown, but the
-// window may be too small to actually show everything.  Resize it if necessary.
-var requiredSize = {};
-requiredSize.innerHeight =
-  40 + 32 + // undo container + bottom margin
-  44 + 32 + // search bar + bottom margin
-  (3 * (180 + 32)) + // 3 rows * (tile height + title and bottom margin)
-  100; // breathing room
-requiredSize.innerWidth =
-  (3 * (290 + 20)) + // 3 cols * (tile width + side margins)
-  100; // breathing room
-
-add_task(async function setupWindowSize() {
-  let [oldSize, curWidth, curHeight] = await ContentTask.spawn(gBrowser.selectedBrowser, requiredSize, (requiredSizeArg) => {
-    var oldSizeVar = {};
-    Object.keys(requiredSizeArg).forEach(prop => {
-      info([prop, content[prop], requiredSizeArg[prop]]);
-      if (content[prop] < requiredSizeArg[prop]) {
-        oldSizeVar[prop] = content[prop];
-        info("Changing browser " + prop + " from " + oldSizeVar[prop] + " to " +
-             requiredSizeArg[prop]);
-        content[prop] = requiredSizeArg[prop];
-      }
-    });
-    return [oldSizeVar, content.outerWidth, content.outerHeight];
-  });
-
-  var screenHeight = {};
-  var screenWidth = {};
-  Cc["@mozilla.org/gfx/screenmanager;1"].
-    getService(Ci.nsIScreenManager).
-    primaryScreen.
-    GetAvailRectDisplayPix({}, {}, screenWidth, screenHeight);
-  screenHeight = screenHeight.value;
-  screenWidth = screenWidth.value;
-
-  if (screenHeight < curHeight) {
-    info("Warning: Browser outer height is now " +
-         curHeight + ", which is larger than the " +
-         "available screen height, " + screenHeight +
-         ". That may cause problems.");
-  }
-
-  if (screenWidth < curWidth) {
-    info("Warning: Browser outer width is now " +
-         curWidth + ", which is larger than the " +
-         "available screen width, " + screenWidth +
-         ". That may cause problems.");
-  }
-
-  registerCleanupFunction(function() {
-    while (gWindow.gBrowser.tabs.length > 1)
-      gWindow.gBrowser.removeTab(gWindow.gBrowser.tabs[1]);
-
-    ContentTask.spawn(gBrowser.selectedBrowser, oldSize, (oldSizeArg) => {
-      Object.keys(oldSizeArg).forEach(prop => {
-        if (oldSizeArg[prop]) {
-          content[prop] = oldSizeArg[prop];
-        }
-      });
-    });
-  });
-});
-
-registerCleanupFunction(function() {
-  Services.prefs.clearUserPref(PREF_NEWTAB_ENABLED);
-});
-
-function pushPrefs(...aPrefs) {
-  return SpecialPowers.pushPrefEnv({"set": aPrefs});
-}
-
-add_task(async function setup() {
-  registerCleanupFunction(function() {
-    return new Promise(resolve => {
-      function cleanupAndFinish() {
-        PlacesUtils.history.clear().then(() => {
-          whenPagesUpdated().then(resolve);
-          NewTabUtils.restore();
-        });
-      }
-
-      let callbacks = NewTabUtils.links._populateCallbacks;
-      let numCallbacks = callbacks.length;
-
-      if (numCallbacks)
-        callbacks.splice(0, numCallbacks, cleanupAndFinish);
-      else
-        cleanupAndFinish();
-    });
-  });
-
-  await whenPagesUpdated();
-});
-
-/** Perform an action on a cell within the newtab page.
-  * @param aIndex index of cell
-  * @param aFn function to call in child process or tab.
-  * @returns result of calling the function.
-  */
-function performOnCell(aIndex, aFn) {
-  return ContentTask.spawn(gWindow.gBrowser.selectedBrowser,
-                           { index: aIndex, fn: aFn.toString() }, async function(args) {
-    let cell = content.gGrid.cells[args.index];
-    // eslint-disable-next-line no-eval
-    return eval(args.fn)(cell);
-  });
-}
-
-/**
- * Allows to provide a list of links that is used to construct the grid.
- * @param aLinksPattern the pattern (see below)
- *
- * Example: setLinks("-1,0,1,2,3")
- * Result: [{url: "http://example.com/", title: "site#-1"},
- *          {url: "http://example0.com/", title: "site#0"},
- *          {url: "http://example1.com/", title: "site#1"},
- *          {url: "http://example2.com/", title: "site#2"},
- *          {url: "http://example3.com/", title: "site#3"}]
- */
-function setLinks(aLinks) {
-  return new Promise(resolve => {
-    let links = aLinks;
-
-    if (typeof links == "string") {
-      links = aLinks.split(/\s*,\s*/).map(function(id) {
-        return {url: "http://example" + (id != "-1" ? id : "") + ".com/",
-                title: "site#" + id};
-      });
-    }
-
-    // Call populateCache() once to make sure that all link fetching that is
-    // currently in progress has ended. We clear the history, fill it with the
-    // given entries and call populateCache() now again to make sure the cache
-    // has the desired contents.
-    NewTabUtils.links.populateCache(function() {
-      PlacesUtils.history.clear().then(() => {
-        fillHistory(links).then(() => {
-          NewTabUtils.links.populateCache(function() {
-            NewTabUtils.allPages.update();
-            resolve();
-          }, true);
-        });
-      });
-    });
-  });
-}
-
-function fillHistory(aLinks) {
-  return new Promise(resolve => {
-    let numLinks = aLinks.length;
-    if (!numLinks) {
-      executeSoon(resolve);
-      return;
-    }
-
-    let transitionLink = Ci.nsINavHistoryService.TRANSITION_LINK;
-
-    // Important: To avoid test failures due to clock jitter on Windows XP, call
-    // Date.now() once here, not each time through the loop.
-    let now = Date.now() * 1000;
-
-    for (let i = 0; i < aLinks.length; i++) {
-      let link = aLinks[i];
-      let place = {
-        uri: makeURI(link.url),
-        title: link.title,
-        // Links are secondarily sorted by visit date descending, so decrease the
-        // visit date as we progress through the array so that links appear in the
-        // grid in the order they're present in the array.
-        visits: [{visitDate: now - i, transitionType: transitionLink}]
-      };
-
-      PlacesUtils.asyncHistory.updatePlaces(place, {
-        handleError: () => ok(false, "couldn't add visit to history"),
-        handleResult() {},
-        handleCompletion() {
-          if (--numLinks == 0) {
-            resolve();
-          }
-        }
-      });
-    }
-  });
-}
-
-/**
- * Allows to specify the list of pinned links (that have a fixed position in
- * the grid.
- * @param aLinksPattern the pattern (see below)
- *
- * Example: setPinnedLinks("3,,1")
- * Result: 'http://example3.com/' is pinned in the first cell. 'http://example1.com/' is
- *         pinned in the third cell.
- */
-function setPinnedLinks(aLinks) {
-  let links = aLinks;
-
-  if (typeof links == "string") {
-    links = aLinks.split(/\s*,\s*/).map(function(id) {
-      if (id)
-        return {url: "http://example" + (id != "-1" ? id : "") + ".com/",
-                title: "site#" + id,
-                type: "history"};
-      return undefined;
-    });
-  }
-
-  Services.prefs.setStringPref("browser.newtabpage.pinned", JSON.stringify(links));
-
-  NewTabUtils.pinnedLinks.resetCache();
-  NewTabUtils.allPages.update();
-}
-
-/**
- * Restore the grid state.
- */
-function restore() {
-  return new Promise(resolve => {
-    whenPagesUpdated().then(resolve);
-    NewTabUtils.restore();
-  });
-}
-
-/**
- * Wait until a given condition becomes true.
- */
-function waitForCondition(aConditionFn, aMaxTries = 50, aCheckInterval = 100) {
-  return new Promise((resolve, reject) => {
-    let tries = 0;
-
-    function tryNow() {
-      tries++;
-
-      if (aConditionFn()) {
-        resolve();
-      } else if (tries < aMaxTries) {
-        tryAgain();
-      } else {
-        reject("Condition timed out: " + aConditionFn.toSource());
-      }
-    }
-
-    function tryAgain() {
-      setTimeout(tryNow, aCheckInterval);
-    }
-
-    tryAgain();
-  });
-}
-
-/**
- * Creates a new tab containing 'about:newtab'.
- */
-async function addNewTabPageTab() {
-  let tab = await BrowserTestUtils.openNewForegroundTab(gWindow.gBrowser, "about:newtab", false);
-  let browser = tab.linkedBrowser;
-
-  // Wait for the document to become visible in case it was preloaded.
-  await waitForCondition(() => !browser.contentDocument.hidden);
-
-  await new Promise(resolve => {
-    if (NewTabUtils.allPages.enabled) {
-      // Continue when the link cache has been populated.
-      NewTabUtils.links.populateCache(function() {
-        whenSearchInitDone().then(resolve);
-      });
-    } else {
-      resolve();
-    }
-  });
-
-  return tab;
-}
-
-/**
- * Compares the current grid arrangement with the given pattern.
- * @param the pattern (see below)
- *
- * Example: checkGrid("3p,2,,4p")
- * Result: We expect the first cell to contain the pinned site 'http://example3.com/'.
- *         The second cell contains 'http://example2.com/'. The third cell is empty.
- *         The fourth cell contains the pinned site 'http://example4.com/'.
- */
-async function checkGrid(pattern) {
-  let length = pattern.split(",").length;
-
-  await ContentTask.spawn(gWindow.gBrowser.selectedBrowser,
-                          { length, pattern }, async function(args) {
-    let grid = content.wrappedJSObject.gGrid;
-
-    let sites = grid.sites.slice(0, args.length);
-    let foundPattern = sites.map(function(aSite) {
-      if (!aSite)
-        return "";
-
-      let pinned = aSite.isPinned();
-      let hasPinnedAttr = aSite.node.hasAttribute("pinned");
-
-      if (pinned != hasPinnedAttr)
-        ok(false, "invalid state (site.isPinned() != site[pinned])");
-
-      return aSite.url.replace(/^http:\/\/example(\d+)\.com\/$/, "$1") + (pinned ? "p" : "");
-    });
-
-    Assert.equal(foundPattern, args.pattern, "grid status = " + args.pattern);
-  });
-}
-
-/**
- * Blocks a site from the grid.
- * @param aIndex The cell index.
- */
-function blockCell(aIndex) {
-  return new Promise(resolve => {
-    whenPagesUpdated().then(resolve);
-    performOnCell(aIndex, cell => {
-      return cell.site.block();
-    });
-  });
-}
-
-/**
- * Pins a site on a given position.
- * @param aIndex The cell index.
- * @param aPinIndex The index the defines where the site should be pinned.
- */
-function pinCell(aIndex) {
-  performOnCell(aIndex, cell => {
-    cell.site.pin();
-  });
-}
-
-/**
- * Unpins the given cell's site.
- * @param aIndex The cell index.
- */
-function unpinCell(aIndex) {
-  return new Promise(resolve => {
-    whenPagesUpdated().then(resolve);
-    performOnCell(aIndex, cell => {
-      cell.site.unpin();
-    });
-  });
-}
-
-/**
- * Simulates a drag and drop operation. Instead of rearranging a site that is
- * is already contained in the newtab grid, this is used to simulate dragging
- * an external link onto the grid e.g. the text from the URL bar.
- * @param aDestIndex The cell index of the drop target.
- */
-async function simulateExternalDrop(aDestIndex) {
-  let pagesUpdatedPromise = whenPagesUpdated();
-
-  await ContentTask.spawn(gWindow.gBrowser.selectedBrowser, aDestIndex, async function(dropIndex) {
-    return new Promise(resolve => {
-      const url = "data:text/html;charset=utf-8," +
-                  "<a id='link' href='http://example99.com/'>link</a>";
-
-      let doc = content.document;
-      let iframe = doc.createElement("iframe");
-
-      function iframeLoaded() {
-        let dataTransfer = new iframe.contentWindow.DataTransfer("dragstart", false);
-        dataTransfer.mozSetDataAt("text/x-moz-url", "http://example99.com/", 0);
-
-        let event = content.document.createEvent("DragEvent");
-        event.initDragEvent("drop", true, true, content, 0, 0, 0, 0, 0,
-                            false, false, false, false, 0, null, dataTransfer);
-
-        let target = content.gGrid.cells[dropIndex].node;
-        target.dispatchEvent(event);
-
-        iframe.remove();
-
-        resolve();
-      }
-
-      iframe.addEventListener("load", function() {
-        content.setTimeout(iframeLoaded, 0);
-      }, {once: true});
-
-      iframe.setAttribute("src", url);
-      iframe.style.width = "50px";
-      iframe.style.height = "50px";
-      iframe.style.position = "absolute";
-      iframe.style.zIndex = 50;
-
-      // the frame has to be attached to a visible element
-      let margin = doc.getElementById("newtab-search-container");
-      margin.appendChild(iframe);
-    });
-  });
-
-  await pagesUpdatedPromise;
-}
-
-/**
- * Resumes testing when all pages have been updated.
- */
-function whenPagesUpdated() {
-  return new Promise(resolve => {
-    let page = {
-      observe: _ => _,
-
-      update() {
-        NewTabUtils.allPages.unregister(this);
-        executeSoon(resolve);
-      }
-    };
-
-    NewTabUtils.allPages.register(page);
-    registerCleanupFunction(function() {
-      NewTabUtils.allPages.unregister(page);
-    });
-  });
-}
-
-/**
- * Waits for the response to the page's initial search state request.
- */
-function whenSearchInitDone() {
-  return ContentTask.spawn(gWindow.gBrowser.selectedBrowser, {}, async function() {
-    return new Promise(resolve => {
-      if (content.gSearch) {
-        let searchController = content.gSearch._contentSearchController;
-        if (searchController.defaultEngine) {
-          resolve();
-          return;
-        }
-      }
-
-      let eventName = "ContentSearchService";
-      content.addEventListener(eventName, function onEvent(event) {
-        if (event.detail.type == "State") {
-          content.removeEventListener(eventName, onEvent);
-          let resolver = function() {
-            // Wait for the search controller to receive the event, then resolve.
-            if (content.gSearch._contentSearchController.defaultEngine) {
-              resolve();
-            }
-          };
-          content.setTimeout(resolver, 0);
-        }
-      });
-    });
-  });
-}
-
-/**
- * Changes the newtab customization option and waits for the panel to open and close
- *
- * @param {string} aTheme
- *        Can be any of("blank"|"classic"|"enhanced")
- */
-function customizeNewTabPage(aTheme) {
-  return ContentTask.spawn(gWindow.gBrowser.selectedBrowser, aTheme, async function(contentTheme) {
-
-    let document = content.document;
-    let panel = document.getElementById("newtab-customize-panel");
-    let customizeButton = document.getElementById("newtab-customize-button");
-
-    function panelOpened(opened) {
-      return new Promise( (resolve) => {
-        let options = {attributes: true, oldValue: true};
-        let observer = new content.MutationObserver(function(mutations) {
-          mutations.forEach(function(mutation) {
-            document.getElementById("newtab-customize-" + contentTheme).click();
-            observer.disconnect();
-            if (opened == panel.hasAttribute("open")) {
-              resolve();
-            }
-          });
-        });
-        observer.observe(panel, options);
-      });
-    }
-
-    let opened = panelOpened(true);
-    customizeButton.click();
-    await opened;
-
-    let closed = panelOpened(false);
-    customizeButton.click();
-    await closed;
-  });
-}
-
-/**
- * Reports presence of a scrollbar
- */
-function hasScrollbar() {
-  return ContentTask.spawn(gWindow.gBrowser.selectedBrowser, {}, async function() {
-    let docElement = content.document.documentElement;
-    return docElement.scrollHeight > docElement.clientHeight;
-  });
-}
deleted file mode 100644
--- a/browser/base/content/test/newtab/searchEngine1x2xLogo.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
-<ShortName>browser_newtab_search searchEngine1x2xLogo.xml</ShortName>
-<Url type="text/html" method="GET" template="http://browser-newtab-search.com/1x2xlogo" rel="searchform"/>
-<!-- #00FF00 -->
-<Image width="65" height="26">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAaCAIAAABn3KYmAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADIGr0+8uwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAL0lEQVRYw+3PAREAAAQEsKd/Z3I4W4NVJtd14uDg4ODg4ODg4ODg4ODg4ODg8Pqw7M0BM+n9I0oAAAAASUVORK5CYII=</Image>
-<!-- #00FFFF -->
-<Image width="130" height="52">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAA0CAIAAADJ8nfCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADMoaoKANQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAYklEQVR42u3RQQ0AAAjEMMC/58MECZ9OwtqVlL4bCzAIAwZhwCAMGIQBgzBgEAYMwoBBGDAIAwZhwCAMGIQBgzBgEAYMwoBBGIQBgzBgEAYMwoBBGDAIAwZhwCAMGIQBg+5ar7sCZiri9VUAAAAASUVORK5CYII=</Image>
-</SearchPlugin>
deleted file mode 100644
--- a/browser/base/content/test/newtab/searchEngine1xLogo.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
-<ShortName>browser_newtab_search searchEngine1xLogo.xml</ShortName>
-<Url type="text/html" method="GET" template="http://browser-newtab-search.com/1xlogo" rel="searchform"/>
-<!-- #FF0000 -->
-<Image width="65" height="26">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAaCAIAAABn3KYmAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADEwS9h64QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAL0lEQVRYw+3PAREAAAQEsKd/Z3I4W4PV5LyOg4ODg4ODg4ODg4ODg4ODg4PD78MC7cwBM02qquMAAAAASUVORK5CYII=</Image>
-</SearchPlugin>
deleted file mode 100644
--- a/browser/base/content/test/newtab/searchEngine2xLogo.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
-<ShortName>browser_newtab_search searchEngine2xLogo.xml</ShortName>
-<Url type="text/html" method="GET" template="http://browser-newtab-search.com/2xlogo" rel="searchform"/>
-<!-- #0000FF -->
-<Image width="130" height="52">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAA0CAIAAADJ8nfCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkTADMURe38sgAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAYklEQVR42u3RQQ0AAAjEsAP/nsEECZ9OwlrJRN+1BRiEAYMwYBAGDMKAQRgwCAMGYcAgDBiEAYMwYBAGDMKAQRgwCAMGYcAgDMKAQRgwCAMGYcAgDBiEAYMwYBAGDMKAQXctkIQBZ/1YP3YAAAAASUVORK5CYII=</Image>
-</SearchPlugin>
deleted file mode 100644
--- a/browser/base/content/test/newtab/searchEngineFavicon.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
-<ShortName>browser_newtab_search searchEngineFavicon.xml</ShortName>
-<Url type="text/html" method="GET" template="http://browser-newtab-search.com/1xlogo" rel="searchform"/>
-<Image width="16" height="16">data:application/ico;base64,AAABAAIAICAAAAEAIACoEAAAJgAAABAQAAABACAAaAQAAM4QAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAATCwAAEwsAAAAAAAAAAAAA/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAABAAAAAgAAAAAQAgAAAAAAAABAAAEwsAABMLAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</Image>
-</SearchPlugin>
deleted file mode 100644
--- a/browser/base/content/test/newtab/searchEngineNoLogo.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
-<ShortName>browser_newtab_search searchEngineNoLogo.xml</ShortName>
-<Url type="text/html" method="GET" template="http://browser-newtab-search.com/nologo" rel="searchform"/>
-</SearchPlugin>
--- a/browser/base/content/test/popupNotifications/head.js
+++ b/browser/base/content/test/popupNotifications/head.js
@@ -124,31 +124,32 @@ function showNotification(notifyObj) {
 function dismissNotification(popup) {
   info("Dismissing notification " + popup.childNodes[0].id);
   executeSoon(() => EventUtils.synthesizeKey("KEY_Escape"));
 }
 
 function BasicNotification(testId) {
   this.browser = gBrowser.selectedBrowser;
   this.id = "test-notification-" + testId;
-  this.message = "This is popup notification for " + testId;
+  this.message = testId + ": Will you allow <> to perform this action?";
   this.anchorID = null;
   this.mainAction = {
     label: "Main Action",
     accessKey: "M",
     callback: () => this.mainActionClicked = true
   };
   this.secondaryActions = [
     {
       label: "Secondary Action",
       accessKey: "S",
       callback: () => this.secondaryActionClicked = true
     }
   ];
   this.options = {
+    name: "http://example.com",
     eventCallback: eventName => {
       switch (eventName) {
         case "dismissed":
           this.dismissalCallbackTriggered = true;
           break;
         case "showing":
           this.showingCallbackTriggered = true;
           break;
@@ -199,23 +200,23 @@ function checkPopup(popup, notifyObj) {
   let icon = document.getAnonymousElementByAttribute(notification, "class",
                                                      "popup-notification-icon");
   if (notifyObj.id == "geolocation") {
     isnot(icon.boxObject.width, 0, "icon for geo displayed");
     ok(popup.anchorNode.classList.contains("notification-anchor-icon"),
        "notification anchored to icon");
   }
 
-  if (typeof notifyObj.message == "string") {
-    is(notification.getAttribute("label"), notifyObj.message, "message matches");
-  } else {
-    is(notification.getAttribute("label"), notifyObj.message.start, "message matches");
-    is(notification.getAttribute("hostname"), notifyObj.message.host, "message matches");
-    is(notification.getAttribute("endlabel"), notifyObj.message.end, "message matches");
-  }
+  let description = notifyObj.message.split("<>");
+  let text = {};
+  text.start = description[0];
+  text.end = description[1];
+  is(notification.getAttribute("label"), text.start, "message matches");
+  is(notification.getAttribute("name"), notifyObj.options.name, "message matches");
+  is(notification.getAttribute("endlabel"), text.end, "message matches");
 
   is(notification.id, notifyObj.id + "-notification", "id matches");
   if (notifyObj.mainAction) {
     is(notification.getAttribute("buttonlabel"), notifyObj.mainAction.label,
        "main action label matches");
     is(notification.getAttribute("buttonaccesskey"),
        notifyObj.mainAction.accessKey, "main action accesskey matches");
     is(notification.getAttribute("buttonhighlight"),
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -45,19 +45,16 @@ if (AppConstants.platform == "macosx")
 var whitelist = [
   // browser/extensions/pdfjs/content/PdfStreamConverter.jsm
   {file: "chrome://pdf.js/locale/chrome.properties"},
   {file: "chrome://pdf.js/locale/viewer.properties"},
 
   // security/manager/pki/resources/content/device_manager.js
   {file: "chrome://pippki/content/load_device.xul"},
 
-  // Used by setting this url as a pref in about:config
-  {file: "chrome://browser/content/newtab/alternativeDefaultSites.json"},
-
   // Add-on compat
   {file: "chrome://global/content/XPCNativeWrapper.js"},
   {file: "chrome://global/locale/brand.dtd"},
 
   // The l10n build system can't package string files only for some platforms.
   // See bug 1339424 for why this is hard to fix.
   {file: "chrome://global/locale/fallbackMenubar.properties",
    platforms: ["linux", "win"]},
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -91,20 +91,16 @@ browser.jar:
         content/browser/defaultthemes/4.header.png    (content/defaultthemes/4.header.png)
         content/browser/defaultthemes/4.icon.png      (content/defaultthemes/4.icon.png)
         content/browser/defaultthemes/4.preview.png   (content/defaultthemes/4.preview.png)
         content/browser/defaultthemes/5.header.png    (content/defaultthemes/5.header.png)
         content/browser/defaultthemes/5.icon.jpg      (content/defaultthemes/5.icon.jpg)
         content/browser/defaultthemes/5.preview.jpg   (content/defaultthemes/5.preview.jpg)
         content/browser/defaultthemes/dark.icon.svg  (content/defaultthemes/dark.icon.svg)
         content/browser/defaultthemes/light.icon.svg (content/defaultthemes/light.icon.svg)
-        content/browser/newtab/newTab.xhtml           (content/newtab/newTab.xhtml)
-*       content/browser/newtab/newTab.js              (content/newtab/newTab.js)
-        content/browser/newtab/newTab.css             (content/newtab/newTab.css)
-        content/browser/newtab/alternativeDefaultSites.json   (content/newtab/alternativeDefaultSites.json)
 *       content/browser/pageinfo/pageInfo.xul         (content/pageinfo/pageInfo.xul)
         content/browser/pageinfo/pageInfo.js          (content/pageinfo/pageInfo.js)
         content/browser/pageinfo/pageInfo.css         (content/pageinfo/pageInfo.css)
         content/browser/pageinfo/feeds.js             (content/pageinfo/feeds.js)
         content/browser/pageinfo/permissions.js       (content/pageinfo/permissions.js)
         content/browser/pageinfo/security.js          (content/pageinfo/security.js)
         content/browser/robot.ico                     (content/robot.ico)
         content/browser/static-robot.png              (content/static-robot.png)
--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -25,17 +25,16 @@ BROWSER_CHROME_MANIFESTS += [
     'content/test/about/browser.ini',
     'content/test/alerts/browser.ini',
     'content/test/captivePortal/browser.ini',
     'content/test/contextMenu/browser.ini',
     'content/test/favicons/browser.ini',
     'content/test/forms/browser.ini',
     'content/test/general/browser.ini',
     'content/test/metaTags/browser.ini',
-    'content/test/newtab/browser.ini',
     'content/test/pageinfo/browser.ini',
     'content/test/performance/browser.ini',
     'content/test/performance/hidpi/browser.ini',
     'content/test/performance/lowdpi/browser.ini',
     'content/test/permissions/browser.ini',
     'content/test/plugins/browser.ini',
     'content/test/popupNotifications/browser.ini',
     'content/test/popups/browser.ini',
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -16,16 +16,18 @@
 #include "mozilla/Preferences.h"
 #include "nsServiceManagerUtils.h"
 
 namespace mozilla {
 namespace browser {
 
 NS_IMPL_ISUPPORTS(AboutRedirector, nsIAboutModule)
 
+bool AboutRedirector::sNewTabPageEnabled = false;
+
 struct RedirEntry {
   const char* id;
   const char* url;
   uint32_t flags;
 };
 
 /*
   Entries which do not have URI_SAFE_FOR_UNTRUSTED_CONTENT will run with chrome
@@ -128,22 +130,31 @@ AboutRedirector::NewChannel(nsIURI* aURI
   NS_ASSERTION(result, "must not be null");
 
   nsAutoCString path = GetAboutModuleName(aURI);
 
   nsresult rv;
   nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  static bool sNTPEnabledCacheInited = false;
+  if (!sNTPEnabledCacheInited) {
+    Preferences::AddBoolVarCache(&AboutRedirector::sNewTabPageEnabled,
+                                 "browser.newtabpage.enabled");
+    sNTPEnabledCacheInited = true;
+  }
+
   for (auto & redir : kRedirMap) {
     if (!strcmp(path.get(), redir.id)) {
       nsAutoCString url;
 
-      if (path.EqualsLiteral("newtab") || path.EqualsLiteral("home")) {
-        // let the aboutNewTabService decide where to redirect
+      // Let the aboutNewTabService decide where to redirect for about:home and
+      // enabled about:newtab. Disabled about:newtab page uses fallback.
+      if (path.EqualsLiteral("home") ||
+          (sNewTabPageEnabled && path.EqualsLiteral("newtab"))) {
         nsCOMPtr<nsIAboutNewTabService> aboutNewTabService =
           do_GetService("@mozilla.org/browser/aboutnewtab-service;1", &rv);
         NS_ENSURE_SUCCESS(rv, rv);
         rv = aboutNewTabService->GetDefaultURL(url);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       // fall back to the specified url in the map
       if (url.IsEmpty()) {
--- a/browser/components/about/AboutRedirector.h
+++ b/browser/components/about/AboutRedirector.h
@@ -19,14 +19,17 @@ public:
 
   AboutRedirector() {}
 
   static nsresult
     Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
 
 protected:
   virtual ~AboutRedirector() {}
+
+private:
+  static bool sNewTabPageEnabled;
 };
 
 } // namespace browser
 } // namespace mozilla
 
 #endif // AboutRedirector_h__
--- a/browser/components/customizableui/test/browser_901207_searchbar_in_panel.js
+++ b/browser/components/customizableui/test/browser_901207_searchbar_in_panel.js
@@ -92,20 +92,18 @@ add_task(async function() {
 
   await waitForSearchBarFocus();
 
   Services.prefs.setBoolPref("browser.search.widget.inNavBar", false);
 });
 
 
 function sendWebSearchKeyCommand() {
-  if (Services.appinfo.OS === "Darwin")
-    EventUtils.synthesizeKey("k", {accelKey: true});
-  else
-    EventUtils.synthesizeKey("k", {ctrlKey: true});
+  document.documentElement.focus();
+  EventUtils.synthesizeKey("k", { accelKey: true });
 }
 
 function logActiveElement() {
   let element = document.activeElement;
   let str = "";
   while (element && element.parentNode) {
     str = " (" + element.localName + "#" + element.id + "." + [...element.classList].join(".") + ") >" + str;
     element = element.parentNode;
--- a/browser/components/customizableui/test/browser_panelUINotifications_fullscreen.js
+++ b/browser/components/customizableui/test/browser_panelUINotifications_fullscreen.js
@@ -14,16 +14,17 @@ add_task(async function testFullscreen()
 
   isnot(PanelUI.notificationPanel.state, "closed", "update-manual doorhanger is showing.");
   let notifications = [...PanelUI.notificationPanel.children].filter(n => !n.hidden);
   is(notifications.length, 1, "PanelUI doorhanger is only displaying one notification.");
   let doorhanger = notifications[0];
   is(doorhanger.id, "appMenu-update-manual-notification", "PanelUI is displaying the update-manual notification.");
 
   let popuphiddenPromise = BrowserTestUtils.waitForEvent(PanelUI.notificationPanel, "popuphidden");
+  document.documentElement.focus();
   EventUtils.synthesizeKey("KEY_F11");
   await popuphiddenPromise;
   await new Promise(executeSoon);
   is(PanelUI.notificationPanel.state, "closed", "update-manual doorhanger is closed.");
 
   FullScreen.showNavToolbox();
   is(PanelUI.menuButton.getAttribute("badge-status"), "update-manual", "Badge is displaying on PanelUI button.");
 
--- a/browser/components/enterprisepolicies/schemas/policies-schema.json
+++ b/browser/components/enterprisepolicies/schemas/policies-schema.json
@@ -91,18 +91,17 @@
         }
       }
     },
 
     "CreateMasterPassword": {
       "description": "If false, removes access to create a master password.",
       "first_available": "60.0",
 
-      "type": "boolean",
-      "enum": [false]
+      "type": "boolean"
     },
 
     "DisableAppUpdate": {
       "description": "Prevent the browser from updating.",
       "first_available": "60.0",
       "enterprise_only": true,
 
       "type": "boolean"
@@ -149,18 +148,17 @@
 
       "type": "boolean"
     },
 
     "DisablePrivateBrowsing": {
       "description": "Disables private browsing.",
       "first_available": "60.0",
 
-      "type": "boolean",
-      "enum": [true]
+      "type": "boolean"
     },
 
     "DisableSysAddonUpdate": {
       "description": "Prevent the browser from installing and updating system addons.",
       "first_available": "60.0",
       "enterprise_only": true,
 
       "type": "boolean",
--- a/browser/components/extensions/test/browser/browser_ext_devtools_network.js
+++ b/browser/components/extensions/test/browser/browser_ext_devtools_network.js
@@ -175,16 +175,18 @@ add_task(async function test_devtools_ne
   extension.sendMessage("navigate");
 
   // Wait till the navigation is complete and request
   // added into the net panel.
   await Promise.all([
     extension.awaitMessage("tabUpdated"),
     extension.awaitMessage("onNavigatedFired"),
     extension.awaitMessage("onRequestFinished"),
+    extension.awaitMessage("onRequestFinished-callbackExecuted"),
+    extension.awaitMessage("onRequestFinished-promiseResolved"),
     waitForRequestAdded(toolbox),
   ]);
 
   // Get HAR, it should not be empty now.
   const getHARPromise = extension.awaitMessage("getHAR-result");
   extension.sendMessage("getHAR");
   const getHARResult = await getHARPromise;
   is(getHARResult.log.entries.length, 1, "HAR log should not be empty");
--- a/browser/components/migration/tests/browser/browser_undo_notification_multiple_dismissal.js
+++ b/browser/components/migration/tests/browser/browser_undo_notification_multiple_dismissal.js
@@ -27,18 +27,18 @@ add_task(async function checkNotificatio
   });
   await OS.File.writeAtomic(path, JSON.stringify(testUndoData), {
     encoding: "utf-8",
     compression: "lz4",
     tmpPath: path + ".tmp",
   });
 
   let firstTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home", false);
+  let secondTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home", false);
   let firstNotification = await getOrWaitForNotification(firstTab.linkedBrowser, "first tab");
-  let secondTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home", false);
   let secondNotification = await getOrWaitForNotification(secondTab.linkedBrowser, "second tab");
 
   // Create a listener for the removal in the first tab, and a listener for bookmarks removal,
   // then click 'Don't keep' in the second tab, and verify that the notification is removed
   // before we start removing bookmarks.
   let haveRemovedBookmark = false;
   let bmObserver;
   let bookmarkRemovedPromise = new Promise(resolve => {
--- a/browser/components/newtab/aboutNewTabService.js
+++ b/browser/components/newtab/aboutNewTabService.js
@@ -10,17 +10,16 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
 ChromeUtils.defineModuleGetter(this, "AboutNewTab",
                                "resource:///modules/AboutNewTab.jsm");
 
 // Dummy references to the files that this service no longer allows loading.
 // Bug 1409054 to remove "chrome://browser/content/abouthome/aboutHome.xhtml"
-// Bug 1433133 to remove "chrome://browser/content/newtab/newTab.xhtml"
 
 const TOPIC_APP_QUIT = "quit-application-granted";
 const TOPIC_LOCALES_CHANGE = "intl:requested-locales-changed";
 
 // Automated tests ensure packaged locales are in this list. Copied output of:
 // https://github.com/mozilla/activity-stream/blob/master/bin/render-activity-stream-html.js
 const ACTIVITY_STREAM_LOCALES = "en-US ach an ar ast az be bg bn-BD bn-IN br bs ca cak cs cy da de dsb el en-GB eo es-AR es-CL es-ES es-MX et eu fa ff fi fr fy-NL ga-IE gd gl gn gu-IN he hi-IN hr hsb hu hy-AM ia id it ja ka kab kk km kn ko lij lo lt ltg lv mk ml mr ms my nb-NO ne-NP nl nn-NO pa-IN pl pt-BR pt-PT rm ro ru si sk sl sq sr sv-SE ta te th tl tr uk ur uz vi zh-CN zh-TW".split(" ");
 
--- a/browser/components/newtab/tests/browser/browser.ini
+++ b/browser/components/newtab/tests/browser/browser.ini
@@ -1,6 +1,7 @@
 [DEFAULT]
 
 [browser_activity_stream_strings.js]
+[browser_enabled_newtabpage.js]
 [browser_packaged_as_locales.js]
 skip-if=true # bug 1423703 comment 20
 [browser_newtab_overrides.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/tests/browser/browser_enabled_newtabpage.js
@@ -0,0 +1,21 @@
+ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+
+function checkSpec(uri, check, message) {
+  const {spec} = NetUtil.newChannel({
+    loadUsingSystemPrincipal: true,
+    uri
+  }).URI;
+
+  info(`got ${spec} for ${uri}`);
+  check(spec, "about:blank", message);
+}
+
+add_task(async function test_newtab_enabled() {
+  checkSpec("about:newtab", isnot, "did not get blank for default about:newtab");
+  checkSpec("about:home", isnot, "did not get blank for default about:home");
+
+  await SpecialPowers.pushPrefEnv({set: [["browser.newtabpage.enabled", false]]});
+
+  checkSpec("about:newtab", is, "got blank when newtab is not enabled");
+  checkSpec("about:home", isnot, "still did not get blank for about:home");
+});
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -2248,16 +2248,20 @@ this.PlacesPanelview = class extends Pla
     } else {
       panelview.removeAttribute("emptyplacesresult");
       try {
         panelview.removeChild(panelview._emptyMenuitem);
       } catch (ex) {}
     }
   }
 
+  _isPopupOpen() {
+    return PanelView.forNode(this._viewElt).active;
+  }
+
   _onPopupHidden(event) {
     let panelview = event.originalTarget;
     let placesNode = panelview._placesNode;
     // Avoid handling ViewHiding of inner views
     if (placesNode && PlacesUIUtils.getViewForNode(panelview) == this) {
       // UI performance: folder queries are cheap, keep the resultnode open
       // so we don't rebuild its contents whenever the popup is reopened.
       // Though, we want to always close feed containers so their expiration
--- a/browser/components/places/tests/browser/browser.ini
+++ b/browser/components/places/tests/browser/browser.ini
@@ -62,16 +62,17 @@ skip-if = (os == 'win' && ccov) # Bug 14
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_copy_query_without_tree.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 subsuite = clipboard
 [browser_cutting_bookmarks.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 subsuite = clipboard
 [browser_drag_bookmarks_on_toolbar.js]
+[browser_enable_toolbar_sidebar.js]
 [browser_forgetthissite_single.js]
 [browser_history_sidebar_search.js]
 [browser_library_batch_delete.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_commands.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_delete_bookmarks_in_tags.js]
 [browser_library_delete_tags.js]
@@ -89,16 +90,17 @@ skip-if = (os == 'win' && ccov) # Bug 14
 [browser_library_openFlatContainer.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_panel_leak.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_search.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_library_views_liveupdate.js]
 [browser_markPageAsFollowedLink.js]
+[browser_panelview_bookmarks_delete.js]
 [browser_paste_bookmarks.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 subsuite = clipboard
 [browser_paste_into_tags.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 [browser_remove_bookmarks.js]
 skip-if = (os == 'win' && ccov) # Bug 1423667
 subsuite = clipboard
new file mode 100644
--- /dev/null
+++ b/browser/components/places/tests/browser/browser_enable_toolbar_sidebar.js
@@ -0,0 +1,66 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Test that the Bookmarks Toolbar and Sidebar can be enabled from the Bookmarks Menu ("View history,
+ * saved bookmarks, and more" button.
+ */
+
+// Cleanup.
+registerCleanupFunction(async () => {
+  CustomizableUI.setToolbarVisibility("PersonalToolbar", false);
+  SidebarUI.hide();
+});
+
+async function selectAppMenuView(buttonId, viewId) {
+  let btn;
+  await BrowserTestUtils.waitForCondition(() => {
+    btn = document.getElementById(buttonId);
+    return btn;
+  }, "Should have the " + buttonId + "button");
+  let view = document.getElementById(viewId);
+  let viewPromise = BrowserTestUtils.waitForEvent(view, "ViewShown");
+  btn.click();
+  await viewPromise;
+}
+
+async function openBookmarkingToolsPanelInLibraryToolbarButton() {
+  await selectAppMenuView("library-button", "appMenu-libraryView");
+  await selectAppMenuView("appMenu-library-bookmarks-button", "PanelUI-bookmarks");
+  await selectAppMenuView("panelMenu_bookmarkingTools", "PanelUI-bookmarkingTools");
+}
+
+add_task(async function test_enable_toolbar() {
+  await openBookmarkingToolsPanelInLibraryToolbarButton();
+
+  let viewBookmarksToolbarBtn;
+  await BrowserTestUtils.waitForCondition(() => {
+    viewBookmarksToolbarBtn = document.getElementById("panelMenu_viewBookmarksToolbar");
+    return viewBookmarksToolbarBtn;
+  }, "Should have the library 'View Bookmarks Toolbar' button.");
+  viewBookmarksToolbarBtn.click();
+  let toolbar;
+  await BrowserTestUtils.waitForCondition(() => {
+    toolbar = document.getElementById("PersonalToolbar");
+    return !toolbar.collapsed;
+  }, "Should have the Bookmarks Toolbar enabled.");
+  Assert.ok(!toolbar.collapsed, "Bookmarks Toolbar is enabled");
+});
+
+add_task(async function test_enable_sidebar() {
+  await openBookmarkingToolsPanelInLibraryToolbarButton();
+
+  let viewBookmarksSidebarBtn;
+  await BrowserTestUtils.waitForCondition(() => {
+    viewBookmarksSidebarBtn = document.getElementById("panelMenu_viewBookmarksSidebar");
+    return viewBookmarksSidebarBtn;
+  }, "Should have the library 'View Bookmarks Sidebar' button.");
+  viewBookmarksSidebarBtn.click();
+  let sidebar;
+  await BrowserTestUtils.waitForCondition(() => {
+    sidebar = document.getElementById("sidebar-box");
+    return !sidebar.hidden;
+  }, "Should have the Bookmarks Sidebar enabled.");
+  Assert.ok(!sidebar.hidden, "Bookmarks Sidebar is enabled");
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/places/tests/browser/browser_panelview_bookmarks_delete.js
@@ -0,0 +1,61 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_URL = "https://www.example.com/";
+
+/**
+ * Checks that the Bookmarks subview is updated after deleting an item.
+ */
+add_task(async function test_panelview_bookmarks_delete() {
+  await PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    url: TEST_URL,
+    title: TEST_URL,
+  });
+
+  let mainView = document.getElementById("appMenu-mainView");
+  let promise = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
+  PanelUI.show();
+  await promise;
+
+  let libraryView = document.getElementById("appMenu-libraryView");
+  promise = BrowserTestUtils.waitForEvent(libraryView, "ViewShown");
+  document.getElementById("appMenu-library-button").click();
+  await promise;
+
+  let bookmarksView = document.getElementById("PanelUI-bookmarks");
+  promise = BrowserTestUtils.waitForEvent(bookmarksView, "ViewShown");
+  document.getElementById("appMenu-library-bookmarks-button").click();
+  await promise;
+
+  let list = document.getElementById("panelMenu_bookmarksMenu");
+  let listItem = [...list.childNodes].find(node => node.label == TEST_URL);
+
+  let placesContext = document.getElementById("placesContext");
+  promise = BrowserTestUtils.waitForEvent(placesContext, "popupshown");
+  EventUtils.synthesizeMouseAtCenter(listItem, {
+    button: 2,
+    type: "contextmenu"
+  });
+  await promise;
+
+  promise = new Promise(resolve => {
+    let observer = new MutationObserver(mutations => {
+      if (listItem.parentNode == null) {
+        Assert.ok(true, "The bookmarks list item was removed.");
+        observer.disconnect();
+        resolve();
+      }
+    });
+    observer.observe(list, { childList: true });
+  });
+  let placesContextDelete = document.getElementById("placesContext_delete");
+  EventUtils.synthesizeMouseAtCenter(placesContextDelete, {});
+  await promise;
+
+  promise = BrowserTestUtils.waitForEvent(PanelUI.panel, "popuphidden");
+  PanelUI.hide();
+  await promise;
+});
--- a/browser/components/preferences/handlers.css
+++ b/browser/components/preferences/handlers.css
@@ -1,20 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #handlersView > richlistitem {
   -moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler");
 }
 
-#handlersView > richlistitem[selected="true"] {
-  -moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler-selected");
-}
-
 #containersView > richlistitem {
   -moz-binding: url("chrome://browser/content/preferences/handlers.xml#container");
 }
 
 /**
  * Make the icons appear.
  * Note: we display the icon box for every item whether or not it has an icon
  * so the labels of all the items align vertically.
--- a/browser/components/preferences/handlers.xml
+++ b/browser/components/preferences/handlers.xml
@@ -12,66 +12,60 @@
   %containersDTD;
 ]>
 
 <bindings id="handlerBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
 
-  <binding id="handler-base" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
+  <binding id="handler" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
     <implementation>
       <property name="type" readonly="true">
         <getter>
           return this.getAttribute("type");
         </getter>
       </property>
+      <!-- Overriding listitem -->
+      <property name="selected" onget="return this.getAttribute('selected') == 'true';">
+        <setter><![CDATA[
+          if (val) {
+            this.setAttribute("selected", "true");
+            gMainPane.rebuildActionsMenu();
+          } else {
+            this.removeAttribute("selected");
+          }
+
+          document.getAnonymousElementByAttribute(this, "anonid", "selected").setAttribute("hidden", !val);
+          document.getAnonymousElementByAttribute(this, "anonid", "not-selected").setAttribute("hidden", !!val);
+
+          return val;
+        ]]></setter>
+      </property>
     </implementation>
-  </binding>
-
-  <binding id="handler" extends="chrome://browser/content/preferences/handlers.xml#handler-base">
     <content>
       <xul:hbox flex="1" equalsize="always">
         <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=typeDescription">
           <xul:image src="moz-icon://goat?size=16" class="typeIcon"
                      xbl:inherits="src=typeIcon" height="16" width="16"/>
           <xul:label flex="1" crop="end" xbl:inherits="value=typeDescription"/>
         </xul:hbox>
-        <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=actionDescription">
+        <xul:hbox anonid="not-selected" flex="1" align="center" xbl:inherits="tooltiptext=actionDescription">
           <xul:image xbl:inherits="src=actionIcon" height="16" width="16" class="actionIcon"/>
           <xul:label flex="1" crop="end" xbl:inherits="value=actionDescription"/>
         </xul:hbox>
-      </xul:hbox>
-    </content>
-  </binding>
-
-  <binding id="handler-selected" extends="chrome://browser/content/preferences/handlers.xml#handler-base">
-    <content>
-      <xul:hbox flex="1" equalsize="always">
-        <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=typeDescription">
-          <xul:image src="moz-icon://goat?size=16" class="typeIcon"
-                     xbl:inherits="src=typeIcon" height="16" width="16"/>
-          <xul:label flex="1" crop="end" xbl:inherits="value=typeDescription"/>
-        </xul:hbox>
-        <xul:hbox flex="1">
+        <xul:hbox hidden="true" anonid="selected" flex="1">
           <xul:menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1"
                         xbl:inherits="tooltiptext=actionDescription"
                         oncommand="gMainPane.onSelectAction(event.originalTarget)">
             <xul:menupopup/>
           </xul:menulist>
         </xul:hbox>
       </xul:hbox>
     </content>
-
-    <implementation>
-      <constructor>
-        gMainPane.rebuildActionsMenu();
-      </constructor>
-    </implementation>
-
   </binding>
 
   <binding id="container">
     <content>
       <xul:hbox flex="1" equalsize="always">
         <xul:hbox flex="1" align="center">
           <xul:hbox xbl:inherits="data-identity-icon=containerIcon,data-identity-color=containerColor" height="24" width="24" class="userContext-icon"/>
           <xul:label flex="1" crop="end" xbl:inherits="xbl:text=containerName,highlightable"/>
--- a/browser/components/preferences/in-content/tests/browser_advanced_update.js
+++ b/browser/components/preferences/in-content/tests/browser_advanced_update.js
@@ -125,17 +125,17 @@ add_task(async function() {
   is(dialogOverlay.style.visibility, "", "The dialog should be invisible");
   let promiseSubDialogLoaded = promiseLoadSubDialog("chrome://mozapps/content/update/history.xul");
   showBtn.doCommand();
   await promiseSubDialogLoaded;
   is(dialogOverlay.style.visibility, "visible", "The dialog should be visible");
 
   let dialogFrame = dialogOverlay.querySelector(".dialogFrame");
   let frameDoc = dialogFrame.contentDocument;
-  let updates = frameDoc.querySelectorAll("update");
+  let updates = frameDoc.querySelectorAll("richlistitem.update");
 
   // Test the update history numbers are correct
   is(updates.length, mockUpdateManager.updateCount, "The update count is incorrect.");
 
   // Test the updates are displayed correctly
   let update = null;
   let updateData = null;
   for (let i = 0; i < updates.length; ++i) {
--- a/browser/components/preferences/in-content/tests/browser_extension_controlled.js
+++ b/browser/components/preferences/in-content/tests/browser_extension_controlled.js
@@ -332,18 +332,18 @@ add_task(async function testExtensionCon
   let manifest = {
     manifest_version: 2,
     name: "set_default_search",
     applications: {gecko: {id: extensionId}},
     description: "set_default_search description",
     permissions: [],
     chrome_settings_overrides: {
       search_provider: {
-        name: "Yahoo",
-        search_url: "https://search.yahoo.com/yhs/search?p=%s&ei=UTF-8&hspart=mozilla&hsimp=yhs-002",
+        name: "DuckDuckGo",
+        search_url: "https://duckduckgo.com/?q={searchTerms}",
         is_default: true,
       },
     }
   };
 
   function setEngine(engine) {
     doc.querySelector(`#defaultEngine menuitem[label="${engine.name}"]`)
        .doCommand();
--- a/browser/components/search/test/browser.ini
+++ b/browser/components/search/test/browser.ini
@@ -32,17 +32,16 @@ skip-if = artifact # bug 1315953
 [browser_healthreport.js]
 [browser_hiddenOneOffs_cleanup.js]
 [browser_hiddenOneOffs_diacritics.js]
 [browser_oneOffContextMenu.js]
 [browser_oneOffContextMenu_setDefault.js]
 [browser_oneOffHeader.js]
 skip-if = os == "mac" #1421238
 [browser_private_search_perwindowpb.js]
-[browser_yahoo.js]
 [browser_abouthome_behavior.js]
 skip-if = true # Bug ??????, Bug 1100301 - leaks windows until shutdown when --run-by-dir
 [browser_aboutSearchReset.js]
 [browser_searchbar_openpopup.js]
 skip-if = os == "linux" # Linux has different focus behaviours.
 [browser_searchbar_keyboard_navigation.js]
 [browser_searchbar_smallpanel_keyboard_navigation.js]
 [browser_searchEngine_behaviors.js]
--- a/browser/components/search/test/browser_abouthome_behavior.js
+++ b/browser/components/search/test/browser_abouthome_behavior.js
@@ -65,23 +65,16 @@ function test() {
     {
       name: "Search with Bing from about:home",
       searchURL: replaceUrl("http://www.bing.com/search?q=foo&pc=MOZI&form=MOZSPG"),
       run() {
         verify_about_home_search("Bing");
       }
     },
     {
-      name: "Search with Yahoo from about:home",
-      searchURL: replaceUrl("https://search.yahoo.com/search?p=foo&ei=UTF-8&fr=moz35"),
-      run() {
-        verify_about_home_search("Yahoo");
-      }
-    },
-    {
       name: "Search with Google from about:home",
       searchURL: replaceUrl("https://www.google.com/search?q=foo&ie=utf-8&oe=utf-8"),
       run() {
         verify_about_home_search("Google");
       }
     },
     {
       name: "Search with Amazon.com from about:home",
--- a/browser/components/search/test/browser_searchEngine_behaviors.js
+++ b/browser/components/search/test/browser_searchEngine_behaviors.js
@@ -42,39 +42,31 @@ const SEARCH_ENGINE_DETAILS = [{
   baseURL: "https://rover.ebay.com/rover/1/711-53200-19255-0/1?ff3=4&toolid=20004&campid=5338192028&customid=&mpre=https://www.ebay.com/sch/foo",
   codes: {
     context: "",
     keyword: "",
     newTab: "",
     submission: "",
   },
   name: "eBay",
-}, {
+},
+// {
 // TODO: Google is tested in browser_google_behaviors.js - we can't test it here
 // yet because of bug 1315953.
 //   alias: "g",
 //   baseURL: "https://www.google.com/search?q=foo&ie=utf-8&oe=utf-8",
 //   codes: {
 //     context: "",
 //     keyword: "",
 //     newTab: "",
 //     submission: "",
 //   },
 //   name: "Google",
-// }, {
-  alias: "y",
-  baseURL: "https://search.yahoo.com/yhs/search?p=foo&ei=UTF-8&hspart=mozilla",
-  codes: {
-    context: "&hsimp=yhs-005",
-    keyword: "&hsimp=yhs-002",
-    newTab: "&hsimp=yhs-004",
-    submission: "&hsimp=yhs-001",
-  },
-  name: "Yahoo",
-}];
+// },
+];
 
 function promiseStateChangeURI() {
   return new Promise(resolve => {
     let listener = {
       onStateChange: function onStateChange(webProgress, req, flags, status) {
         info("onStateChange");
         // Only care about top-level document starts
         let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
deleted file mode 100644
--- a/browser/components/search/test/browser_yahoo.js
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * Test Yahoo search plugin URLs
- */
-
-"use strict";
-
-const BROWSER_SEARCH_PREF = "browser.search.";
-
-add_task(async function test() {
-  await SpecialPowers.pushPrefEnv({ set: [
-    ["browser.search.widget.inNavBar", true],
-  ]});
-
-  let engine = Services.search.getEngineByName("Yahoo");
-  ok(engine, "Yahoo");
-
-  let base = "https://search.yahoo.com/yhs/search?p=foo&ei=UTF-8&hspart=mozilla";
-  let url;
-
-  // Test search URLs (including purposes).
-  url = engine.getSubmission("foo").uri.spec;
-  is(url, base + "&hsimp=yhs-001", "Check search URL for 'foo'");
-  url = engine.getSubmission("foo", null, "searchbar").uri.spec;
-  is(url, base + "&hsimp=yhs-001", "Check search bar search URL for 'foo'");
-  url = engine.getSubmission("foo", null, "keyword").uri.spec;
-  is(url, base + "&hsimp=yhs-002", "Check keyword search URL for 'foo'");
-  url = engine.getSubmission("foo", null, "homepage").uri.spec;
-  is(url, base + "&hsimp=yhs-003", "Check homepage search URL for 'foo'");
-  url = engine.getSubmission("foo", null, "newtab").uri.spec;
-  is(url, base + "&hsimp=yhs-004", "Check newtab search URL for 'foo'");
-  url = engine.getSubmission("foo", null, "contextmenu").uri.spec;
-  is(url, base + "&hsimp=yhs-005", "Check context menu search URL for 'foo'");
-  url = engine.getSubmission("foo", null, "system").uri.spec;
-  is(url, base + "&hsimp=yhs-007", "Check system search URL for 'foo'");
-  url = engine.getSubmission("foo", null, "invalid").uri.spec;
-  is(url, base + "&hsimp=yhs-001", "Check invalid URL for 'foo'");
-
-  // Check search suggestion URL.
-  url = engine.getSubmission("foo", "application/x-suggestions+json").uri.spec;
-  is(url, "https://search.yahoo.com/sugg/ff?output=fxjson&appid=ffd&command=foo", "Check search suggestion URL for 'foo'");
-
-  // Check all other engine properties.
-  const EXPECTED_ENGINE = {
-    name: "Yahoo",
-    alias: null,
-    description: "Yahoo Search",
-    searchForm: "https://search.yahoo.com/yhs/search?p=&ei=UTF-8&hspart=mozilla&hsimp=yhs-001",
-    hidden: false,
-    wrappedJSObject: {
-      queryCharset: "UTF-8",
-      "_iconURL": "resource://search-plugins/images/yahoo.ico",
-      _urls: [
-        {
-          type: "application/x-suggestions+json",
-          method: "GET",
-          template: "https://search.yahoo.com/sugg/ff",
-          params: [
-            {
-              name: "output",
-              value: "fxjson",
-              purpose: undefined,
-            },
-            {
-              name: "appid",
-              value: "ffd",
-              purpose: undefined,
-            },
-            {
-              name: "command",
-              value: "{searchTerms}",
-              purpose: undefined,
-            },
-          ],
-        },
-        {
-          type: "text/html",
-          method: "GET",
-          template: "https://search.yahoo.com/yhs/search",
-          params: [
-            {
-              name: "p",
-              value: "{searchTerms}",
-              purpose: undefined,
-            },
-            {
-              name: "ei",
-              value: "UTF-8",
-              purpose: undefined,
-            },
-            {
-              name: "hspart",
-              value: "mozilla",
-              purpose: undefined,
-            },
-            {
-              name: "hsimp",
-              value: "yhs-001",
-              purpose: "searchbar",
-            },
-            {
-              name: "hsimp",
-              value: "yhs-002",
-              purpose: "keyword",
-            },
-            {
-              name: "hsimp",
-              value: "yhs-003",
-              purpose: "homepage",
-            },
-            {
-              name: "hsimp",
-              value: "yhs-004",
-              purpose: "newtab",
-            },
-            {
-              name: "hsimp",
-              value: "yhs-005",
-              purpose: "contextmenu",
-            },
-            {
-              name: "hsimp",
-              value: "yhs-007",
-              purpose: "system",
-            },
-          ],
-          mozparams: {},
-        },
-      ],
-    },
-  };
-
-  isSubObjectOf(EXPECTED_ENGINE, engine, "Yahoo");
-});
--- a/browser/extensions/screenshots/webextension/selector/shooter.js
+++ b/browser/extensions/screenshots/webextension/selector/shooter.js
@@ -79,19 +79,17 @@ this.shooter = (function() { // eslint-d
   };
 
   function screenshotPageAsync(selectedPos, captureType) {
     if (!supportsDrawWindow) {
       return Promise.resolve(null);
     }
     const canvas = captureToCanvas(selectedPos, captureType);
     ui.iframe.showLoader();
-    const width = selectedPos.right - selectedPos.left;
-    const height = selectedPos.bottom - selectedPos.top;
-    const imageData = canvas.getContext("2d").getImageData(0, 0, width, height);
+    const imageData = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height);
     return callBackground("canvasToDataURL", imageData);
   }
 
   let isSaving = null;
 
   exports.takeShot = function(captureType, selectedPos, url) {
     // isSaving indicates we're aleady in the middle of saving
     // we use a timeout so in the case of a failure the button will
@@ -175,18 +173,18 @@ this.shooter = (function() { // eslint-d
       }
     }).then(() => {
       if (deactivateAfterFinish) {
         uicontrol.deactivate();
       }
     }));
   };
 
-  exports.downloadShot = function(selectedPos, previewDataUrl) {
-    const shotPromise = previewDataUrl ? Promise.resolve(previewDataUrl) : screenshotPageAsync(selectedPos, "fullPage");
+  exports.downloadShot = function(selectedPos, previewDataUrl, type) {
+    const shotPromise = previewDataUrl ? Promise.resolve(previewDataUrl) : screenshotPageAsync(selectedPos, type);
     catcher.watchPromise(shotPromise.then(dataUrl => {
       let promise = Promise.resolve(dataUrl);
       if (!dataUrl) {
         promise = callBackground(
           "screenshotPage",
           selectedPos.asJson(),
           {
             scrollX: window.scrollX,
@@ -209,34 +207,34 @@ this.shooter = (function() { // eslint-d
         });
         ui.triggerDownload(dataUrl, shotObject.filename);
         uicontrol.deactivate();
       }));
     }))
   };
 
   let copyInProgress = null;
-  exports.copyShot = function(selectedPos, previewDataUrl) {
+  exports.copyShot = function(selectedPos, previewDataUrl, type) {
     // This is pretty slow. We'll ignore additional user triggered copy events
     // while it is in progress.
     if (copyInProgress) {
       return;
     }
     // A max of five seconds in case some error occurs.
     copyInProgress = setTimeout(() => {
       copyInProgress = null;