merge m-c -> oak
authorNick Alexander <nalexander@mozilla.com>
Wed, 01 Nov 2017 11:52:26 -0700
changeset 1476571 c417568b0ed7f517860b6a3f01e92424f53b766c
parent 1476570 870c767241258039952693bc3e14581035fa27f9 (current diff)
parent 1338974 cd7217cf05a2332a8fd7b498767a07b2c31ea657 (diff)
child 1476572 ee13a49bc976e98912923c6d48f6d67272e70a33
push id263306
push usercatlee@mozilla.com
push dateFri, 06 Apr 2018 15:43:50 +0000
treeherdertry@a0bfb6549eeb [default view] [failures only]
milestone58.0a1
merge m-c -> oak MozReview-Commit-ID: JmHe8f4PX2E
browser/base/content/browser.css
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_bug561636.js
browser/base/content/test/general/browser_bug595507.js
browser/base/content/test/plugins/browser_CTP_multi_allow.js
browser/base/content/test/plugins/browser_plugins_added_dynamically.js
browser/locales/en-US/chrome/browser/browser.properties
browser/modules/test/browser/browser_bug1319078.js
browser/themes/shared/notification-icons.inc.css
devtools/client/debugger/new/test/mochitest/browser_dbg-search-sources.js
devtools/client/debugger/new/test/mochitest/browser_dbg-search-symbols.js
devtools/shim/aboutdevtools/images/otter.png
dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl
mobile/android/base/Makefile.in
mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/StreamHighlightItemRowContextMenuListener.java
mobile/android/moz.configure
old-configure.in
python/mozbuild/mozbuild/test/frontend/data/host-defines/moz.build
third_party/rust/bindgen-0.29.1/.cargo-checksum.json
third_party/rust/bindgen-0.29.1/.github/ISSUE_TEMPLATE.md
third_party/rust/bindgen-0.29.1/.travis.yml
third_party/rust/bindgen-0.29.1/CONTRIBUTING.md
third_party/rust/bindgen-0.29.1/Cargo.toml
third_party/rust/bindgen-0.29.1/LICENSE
third_party/rust/bindgen-0.29.1/README.md
third_party/rust/bindgen-0.29.1/appveyor.yml
third_party/rust/bindgen-0.29.1/book/book.toml
third_party/rust/bindgen-0.29.1/book/src/SUMMARY.md
third_party/rust/bindgen-0.29.1/book/src/blacklisting.md
third_party/rust/bindgen-0.29.1/book/src/chapter_1.md
third_party/rust/bindgen-0.29.1/book/src/command-line-usage.md
third_party/rust/bindgen-0.29.1/book/src/cpp.md
third_party/rust/bindgen-0.29.1/book/src/customizing-generated-bindings.md
third_party/rust/bindgen-0.29.1/book/src/introduction.md
third_party/rust/bindgen-0.29.1/book/src/library-usage.md
third_party/rust/bindgen-0.29.1/book/src/nocopy.md
third_party/rust/bindgen-0.29.1/book/src/opaque.md
third_party/rust/bindgen-0.29.1/book/src/replacing-types.md
third_party/rust/bindgen-0.29.1/book/src/requirements.md
third_party/rust/bindgen-0.29.1/book/src/tutorial-0.md
third_party/rust/bindgen-0.29.1/book/src/tutorial-1.md
third_party/rust/bindgen-0.29.1/book/src/tutorial-2.md
third_party/rust/bindgen-0.29.1/book/src/tutorial-3.md
third_party/rust/bindgen-0.29.1/book/src/tutorial-4.md
third_party/rust/bindgen-0.29.1/book/src/tutorial-5.md
third_party/rust/bindgen-0.29.1/book/src/tutorial-6.md
third_party/rust/bindgen-0.29.1/book/src/using-unions.md
third_party/rust/bindgen-0.29.1/book/src/whitelisting.md
third_party/rust/bindgen-0.29.1/build.rs
third_party/rust/bindgen-0.29.1/ci/assert-docs.sh
third_party/rust/bindgen-0.29.1/ci/assert-no-diff.bat
third_party/rust/bindgen-0.29.1/ci/assert-no-diff.sh
third_party/rust/bindgen-0.29.1/ci/assert-rustfmt.sh
third_party/rust/bindgen-0.29.1/ci/before_install.sh
third_party/rust/bindgen-0.29.1/ci/deploy-book.sh
third_party/rust/bindgen-0.29.1/ci/no-includes.sh
third_party/rust/bindgen-0.29.1/ci/test-book.sh
third_party/rust/bindgen-0.29.1/ci/test.bat
third_party/rust/bindgen-0.29.1/ci/test.sh
third_party/rust/bindgen-0.29.1/example-graphviz-ir.png
third_party/rust/bindgen-0.29.1/rustfmt.toml
third_party/rust/bindgen-0.29.1/src/callbacks.rs
third_party/rust/bindgen-0.29.1/src/clang.rs
third_party/rust/bindgen-0.29.1/src/codegen/error.rs
third_party/rust/bindgen-0.29.1/src/codegen/helpers.rs
third_party/rust/bindgen-0.29.1/src/codegen/mod.rs
third_party/rust/bindgen-0.29.1/src/codegen/struct_layout.rs
third_party/rust/bindgen-0.29.1/src/extra_assertions.rs
third_party/rust/bindgen-0.29.1/src/ir/analysis/derive_debug.rs
third_party/rust/bindgen-0.29.1/src/ir/analysis/has_vtable.rs
third_party/rust/bindgen-0.29.1/src/ir/analysis/mod.rs
third_party/rust/bindgen-0.29.1/src/ir/analysis/template_params.rs
third_party/rust/bindgen-0.29.1/src/ir/annotations.rs
third_party/rust/bindgen-0.29.1/src/ir/comment.rs
third_party/rust/bindgen-0.29.1/src/ir/comp.rs
third_party/rust/bindgen-0.29.1/src/ir/context.rs
third_party/rust/bindgen-0.29.1/src/ir/derive.rs
third_party/rust/bindgen-0.29.1/src/ir/dot.rs
third_party/rust/bindgen-0.29.1/src/ir/enum_ty.rs
third_party/rust/bindgen-0.29.1/src/ir/function.rs
third_party/rust/bindgen-0.29.1/src/ir/int.rs
third_party/rust/bindgen-0.29.1/src/ir/item.rs
third_party/rust/bindgen-0.29.1/src/ir/item_kind.rs
third_party/rust/bindgen-0.29.1/src/ir/layout.rs
third_party/rust/bindgen-0.29.1/src/ir/mod.rs
third_party/rust/bindgen-0.29.1/src/ir/module.rs
third_party/rust/bindgen-0.29.1/src/ir/objc.rs
third_party/rust/bindgen-0.29.1/src/ir/template.rs
third_party/rust/bindgen-0.29.1/src/ir/traversal.rs
third_party/rust/bindgen-0.29.1/src/ir/ty.rs
third_party/rust/bindgen-0.29.1/src/ir/var.rs
third_party/rust/bindgen-0.29.1/src/lib.rs
third_party/rust/bindgen-0.29.1/src/log_stubs.rs
third_party/rust/bindgen-0.29.1/src/main.rs
third_party/rust/bindgen-0.29.1/src/options.rs
third_party/rust/bindgen-0.29.1/src/parse.rs
third_party/rust/bindgen-0.29.1/src/regex_set.rs
third_party/rust/bindgen-0.29.1/src/uses.rs
third_party/rust/bindgen/src/codegen/derive_debug.rs
third_party/rust/bindgen/src/ir/analysis/derive_partial_eq.rs
toolkit/components/browser/nsCommandHandler.cpp
toolkit/components/browser/nsCommandHandler.h
toolkit/components/browser/nsEmbedStream.cpp
toolkit/components/browser/nsEmbedStream.h
toolkit/components/browser/nsICommandHandler.idl
toolkit/components/browser/nsIWebBrowserStream.idl
toolkit/components/telemetry/Histograms.json
toolkit/mozapps/installer/packager.mk
toolkit/themes/shared/plugins/pluginBlocked.svg
xpcom/base/LinuxUtils.cpp
xpcom/base/LinuxUtils.h
xpcom/base/SystemMemoryReporter.cpp
xpcom/base/SystemMemoryReporter.h
xpcom/build/XPCOMInit.cpp
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -137,84 +137,103 @@ var gPluginHandler = {
     }
   },
 
   /**
    * Called from the plugin doorhanger to set the new permissions for a plugin
    * and activate plugins if necessary.
    * aNewState should be either "allownow" "allowalways" or "block"
    */
-  _updatePluginPermission(aNotification, aPluginInfo, aNewState) {
+  _updatePluginPermission(aBrowser, aPluginInfo, aNewState) {
     let permission;
     let expireType;
     let expireTime;
     let histogram =
-      Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_USER_ACTION");
+      Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_USER_ACTION_2");
+
+    let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
 
     // Update the permission manager.
     // Also update the current state of pluginInfo.fallbackType so that
     // subsequent opening of the notification shows the current state.
     switch (aNewState) {
       case "allownow":
         permission = Ci.nsIPermissionManager.ALLOW_ACTION;
         expireType = Ci.nsIPermissionManager.EXPIRE_SESSION;
         expireTime = Date.now() + Services.prefs.getIntPref(this.PREF_SESSION_PERSIST_MINUTES) * 60 * 1000;
         histogram.add(0);
         aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE;
-        aNotification.options.extraAttr = "active";
+        notification.options.extraAttr = "active";
         break;
 
       case "allowalways":
         permission = Ci.nsIPermissionManager.ALLOW_ACTION;
         expireType = Ci.nsIPermissionManager.EXPIRE_TIME;
         expireTime = Date.now() +
           Services.prefs.getIntPref(this.PREF_PERSISTENT_DAYS) * 24 * 60 * 60 * 1000;
         histogram.add(1);
         aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE;
-        aNotification.options.extraAttr = "active";
+        notification.options.extraAttr = "active";
         break;
 
       case "block":
         permission = Ci.nsIPermissionManager.PROMPT_ACTION;
         expireType = Ci.nsIPermissionManager.EXPIRE_NEVER;
         expireTime = 0;
         histogram.add(2);
         switch (aPluginInfo.blocklistState) {
           case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE:
             aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE;
             break;
           case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE:
             aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
             break;
           default:
-            aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY;
+            // PLUGIN_CLICK_TO_PLAY_QUIET will only last until they reload the page, at
+            // which point it will be PLUGIN_CLICK_TO_PLAY (the overlays will appear)
+            aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET;
         }
-        aNotification.options.extraAttr = "inactive";
+        notification.options.extraAttr = "inactive";
         break;
 
-      // In case a plugin has already been allowed in another tab, the "continue allowing" button
-      // shouldn't change any permissions but should run the plugin-enablement code below.
+      case "blockalways":
+        permission = Ci.nsIObjectLoadingContent.PLUGIN_PERMISSION_PROMPT_ACTION_QUIET;
+        expireType = Ci.nsIPermissionManager.EXPIRE_NEVER;
+        expireTime = 0;
+        histogram.add(3);
+        aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET;
+        notification.options.extraAttr = "inactive";
+        break;
+
+      // In case a plugin has already been allowed/disallowed in another tab, the
+      // buttons matching the existing block state shouldn't change any permissions
+      // but should run the plugin-enablement code below.
       case "continue":
         aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE;
-        aNotification.options.extraAttr = "active";
+        notification.options.extraAttr = "active";
         break;
+
+      case "continueblocking":
+        aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET;
+        notification.options.extraAttr = "inactive";
+        break;
+
       default:
         Cu.reportError(Error("Unexpected plugin state: " + aNewState));
         return;
     }
 
-    let browser = aNotification.browser;
-    if (aNewState != "continue") {
-      let principal = aNotification.options.principal;
+    if (aNewState != "continue" && aNewState != "continueblocking") {
+      let principal = notification.options.principal;
       Services.perms.addFromPrincipal(principal, aPluginInfo.permissionString,
                                       permission, expireType, expireTime);
       aPluginInfo.pluginPermissionType = expireType;
     }
 
-    browser.messageManager.sendAsyncMessage("BrowserPlugins:ActivatePlugins", {
+    aBrowser.messageManager.sendAsyncMessage("BrowserPlugins:ActivatePlugins", {
       pluginInfo: aPluginInfo,
       newState: aNewState,
     });
   },
 
   showClickToPlayNotification(browser, plugins, showNow,
                                         principal, location) {
     // It is possible that we've received a message from the frame script to show
@@ -240,26 +259,21 @@ var gPluginHandler = {
     // If this is a new notification, create a pluginData map, otherwise append
     let pluginData;
     if (notification) {
       pluginData = notification.options.pluginData;
     } else {
       pluginData = new Map();
     }
 
-    let hasInactivePlugins = true;
-    for (var pluginInfo of plugins) {
+    for (let pluginInfo of plugins) {
       if (pluginData.has(pluginInfo.permissionString)) {
         continue;
       }
 
-      if (pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
-        hasInactivePlugins = false;
-      }
-
       // If a block contains an infoURL, we should always prefer that to the default
       // URL that we construct in-product, even for other blocklist types.
       let url = Services.blocklist.getPluginInfoURL(pluginInfo.pluginTag);
 
       if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
         if (!url) {
           url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
         }
@@ -282,40 +296,115 @@ var gPluginHandler = {
       if (showNow) {
         notification.options.primaryPlugin = primaryPluginPermission;
         notification.reshow();
         browser.messageManager.sendAsyncMessage("BrowserPlugins:NotificationShown");
       }
       return;
     }
 
-    let options = {
-      dismissed: !showNow,
-      persistent: showNow,
-      eventCallback: this._clickToPlayNotificationEventCallback,
-      primaryPlugin: primaryPluginPermission,
-      pluginData,
-      principal,
-      extraAttr: hasInactivePlugins ? "inactive" : "active",
-    };
+    if (plugins.length == 1) {
+      let pluginInfo = plugins[0];
+      // If a block contains an infoURL, we should always prefer that to the default
+      // URL that we construct in-product, even for other blocklist types.
+      let url = Services.blocklist.getPluginInfoURL(pluginInfo.pluginTag);
+
+      if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
+        if (!url) {
+          url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
+        }
+      } else {
+        url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "clicktoplay";
+      }
+      pluginInfo.detailsLink = url;
+
+      let chromeWin = window.QueryInterface(Ci.nsIDOMChromeWindow);
+      let isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(chromeWin);
+
+      let active = pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE;
+
+      let options = {
+        dismissed: !showNow,
+        hideClose: !Services.prefs.getBoolPref("privacy.permissionPrompts.showCloseButton"),
+        persistent: showNow,
+        eventCallback: this._clickToPlayNotificationEventCallback,
+        primaryPlugin: primaryPluginPermission,
+        popupIconClass: "plugin-icon",
+        extraAttr: active ? "active" : "inactive",
+        pluginData,
+        principal,
+      };
+
+      let description;
+      if (pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE) {
+        description = gNavigatorBundle.getString("flashActivate.outdated.message");
+      } else {
+        description = gNavigatorBundle.getString("flashActivate.message");
+      }
+
+      let badge = document.getElementById("plugin-icon-badge");
+      badge.setAttribute("animate", "true");
+      badge.addEventListener("animationend", function animListener(event) {
+        if (event.animationName == "blink-badge" &&
+            badge.hasAttribute("animate")) {
+          badge.removeAttribute("animate");
+          badge.removeEventListener("animationend", animListener);
+        }
+      });
 
-    let badge = document.getElementById("plugin-icon-badge");
-    badge.setAttribute("animate", "true");
-    badge.addEventListener("animationend", function animListener(event) {
-      if (event.animationName == "blink-badge" &&
-          badge.hasAttribute("animate")) {
-        badge.removeAttribute("animate");
-        badge.removeEventListener("animationend", animListener);
+      let weakBrowser = Cu.getWeakReference(browser);
+      let mainAction = {
+        callback: ({checkboxChecked}) => {
+          let browserRef = weakBrowser.get();
+          if (browserRef) {
+            if (checkboxChecked) {
+              this._updatePluginPermission(browserRef, pluginInfo, "allowalways");
+            } else if (pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
+              this._updatePluginPermission(browserRef, pluginInfo, "continue");
+            } else {
+              this._updatePluginPermission(browserRef, pluginInfo, "allownow");
+            }
+          }
+        },
+        label: gNavigatorBundle.getString("flashActivate.allow"),
+        accessKey: gNavigatorBundle.getString("flashActivate.allow.accesskey"),
+        dismiss: true,
+      };
+
+      let secondaryActions = null;
+      if (!isWindowPrivate) {
+        options.checkbox = {
+          label: gNavigatorBundle.getString("flashActivate.remember"),
+        };
+        secondaryActions = [{
+          callback: ({checkboxChecked}) => {
+            let browserRef = weakBrowser.get();
+            if (browserRef) {
+              if (checkboxChecked) {
+                this._updatePluginPermission(browserRef, pluginInfo, "blockalways");
+              } else if (pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
+                this._updatePluginPermission(browserRef, pluginInfo, "block");
+              } else {
+                this._updatePluginPermission(browserRef, pluginInfo, "continueblocking");
+              }
+            }
+          },
+          label: gNavigatorBundle.getString("flashActivate.noAllow"),
+          accessKey: gNavigatorBundle.getString("flashActivate.noAllow.accesskey"),
+          dismiss: true,
+        }];
       }
-    });
 
-    PopupNotifications.show(browser, "click-to-play-plugins",
-                            "", "plugins-notification-icon",
-                            null, null, options);
-    browser.messageManager.sendAsyncMessage("BrowserPlugins:NotificationShown");
+      PopupNotifications.show(browser, "click-to-play-plugins",
+                                             description, "plugins-notification-icon",
+                                             mainAction, secondaryActions, options);
+      browser.messageManager.sendAsyncMessage("BrowserPlugins:NotificationShown");
+    } else {
+      this.removeNotification(browser, "click-to-play-plugins");
+    }
   },
 
   removeNotification(browser, name) {
     let notification = PopupNotifications.getNotification(name, browser);
     if (notification)
       PopupNotifications.remove(notification);
   },
 
@@ -405,16 +494,17 @@ var gPluginHandler = {
       let brand = document.getElementById("bundle_brand").getString("brandShortName");
 
       if (actions.length == 1) {
         let pluginInfo = actions[0];
         let pluginName = pluginInfo.pluginName;
 
         switch (pluginInfo.fallbackType) {
           case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
+          case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET:
             message = gNavigatorBundle.getFormattedString(
               "pluginActivationWarning.message",
               [brand]);
             break;
           case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
             message = gNavigatorBundle.getFormattedString(
               "pluginActivateOutdated.message",
               [pluginName, origin, brand]);
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -997,25 +997,16 @@ html|*#fullscreen-exit-button {
   pointer-events: none;
   -moz-stack-sizing: ignore;
 }
 
 #addon-progress-notification {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#addon-progress-notification");
 }
 
-#click-to-play-plugins-notification {
-  -moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification");
-}
-
-
-.plugin-popupnotification-centeritem {
-  -moz-binding: url("chrome://browser/content/urlbarBindings.xml#plugin-popupnotification-center-item");
-}
-
 browser[tabmodalPromptShowing] {
   -moz-user-focus: none !important;
 }
 
 /* Status panel */
 
 statuspanel {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#statuspanel");
--- a/browser/base/content/test/plugins/browser.ini
+++ b/browser/base/content/test/plugins/browser.ini
@@ -60,36 +60,32 @@ skip-if = !crashreporter
 tags = blocklist
 [browser_CTP_drag_drop.js]
 tags = blocklist
 [browser_CTP_favorfallback.js]
 [browser_CTP_hide_overlay.js]
 tags = blocklist
 [browser_CTP_iframe.js]
 tags = blocklist
-[browser_CTP_multi_allow.js]
-tags = blocklist
 [browser_CTP_nonplugins.js]
 tags = blocklist
 [browser_CTP_notificationBar.js]
 tags = blocklist
 [browser_CTP_outsideScrollArea.js]
 tags = blocklist
 [browser_CTP_remove_navigate.js]
 tags = blocklist
 [browser_CTP_resize.js]
 tags = blocklist
 [browser_CTP_shouldShowOverlay.js]
 [browser_CTP_zoom.js]
 tags = blocklist
 [browser_blocking.js]
 tags = blocklist
 [browser_iterate_hidden_plugins.js]
-[browser_plugins_added_dynamically.js]
-tags = blocklist
 [browser_pluginnotification.js]
 tags = blocklist
 [browser_plugin_reloading.js]
 tags = blocklist
 [browser_blocklist_content.js]
 skip-if = !e10s
 tags = blocklist
 [browser_enable_DRM_prompt.js]
--- a/browser/base/content/test/plugins/browser_CTP_context_menu.js
+++ b/browser/base/content/test/plugins/browser_CTP_context_menu.js
@@ -56,14 +56,14 @@ add_task(async function() {
   ok(actMenuItem, "Should have a context menu entry for activating the plugin");
 
   // Activate the plugin via the context menu
   EventUtils.synthesizeMouseAtCenter(actMenuItem, {});
 
   await promiseForCondition(() => !PopupNotifications.panel.dismissed && PopupNotifications.panel.firstChild);
 
   // Activate the plugin
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   // check plugin state
   pluginInfo = await promiseForPluginInfo("test", gBrowser.selectedBrowser);
   ok(pluginInfo.activated, "plugin should not be activated");
 });
--- a/browser/base/content/test/plugins/browser_CTP_crashreporting.js
+++ b/browser/base/content/test/plugins/browser_CTP_crashreporting.js
@@ -70,17 +70,17 @@ add_task(async function() {
     await promiseUpdatePluginBindings(browser);
 
     let pluginInfo = await promiseForPluginInfo("test", browser);
     ok(!pluginInfo.activated, "Plugin should not be activated");
 
     // Simulate clicking the "Allow Always" button.
     let notification = PopupNotifications.getNotification("click-to-play-plugins", browser);
     await promiseForNotificationShown(notification, browser);
-    PopupNotifications.panel.firstChild._primaryButton.click();
+    PopupNotifications.panel.firstChild.button.click();
 
     // Prepare a crash report topic observer that only returns when
     // the crash report has been successfully sent.
     let crashReportChecker = (subject, data) => {
       return (data == "success");
     };
     let crashReportPromise = TestUtils.topicObserved("crash-report-status",
                                                      crashReportChecker);
--- a/browser/base/content/test/plugins/browser_CTP_drag_drop.js
+++ b/browser/base/content/test/plugins/browser_CTP_drag_drop.js
@@ -84,13 +84,13 @@ add_task(async function() {
   });
 
   let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gNewWindow.gBrowser.selectedBrowser).dismissed && gNewWindow.PopupNotifications.panel.firstChild;
   await promiseForCondition(condition);
 });
 
 add_task(async function() {
   // Click the activate button on doorhanger to make sure it works
-  gNewWindow.PopupNotifications.panel.firstChild._primaryButton.click();
+  gNewWindow.PopupNotifications.panel.firstChild.button.click();
 
   let pluginInfo = await promiseForPluginInfo("test", gNewWindow.gBrowser.selectedBrowser);
   ok(pluginInfo.activated, "plugin should be activated");
 });
deleted file mode 100644
--- a/browser/base/content/test/plugins/browser_CTP_multi_allow.js
+++ /dev/null
@@ -1,99 +0,0 @@
-var rootDir = getRootDirectory(gTestPath);
-const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
-var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
-
-add_task(async function() {
-  registerCleanupFunction(function() {
-    clearAllPluginPermissions();
-    setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
-    setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in");
-    Services.prefs.clearUserPref("plugins.click_to_play");
-    Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
-    gBrowser.removeCurrentTab();
-    window.focus();
-  });
-});
-
-add_task(async function() {
-  Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
-
-  gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
-
-  Services.prefs.setBoolPref("plugins.click_to_play", true);
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in");
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in");
-
-  await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_two_types.html");
-
-  // Work around for delayed PluginBindingAttached
-  await promiseUpdatePluginBindings(gBrowser.selectedBrowser);
-
-  // Test that the click-to-play doorhanger for multiple plugins shows the correct
-  // state when re-opening without reloads or navigation.
-
-  let pluginInfo = await promiseForPluginInfo("test", gBrowser.selectedBrowser);
-  ok(!pluginInfo.activated, "plugin should be activated");
-
-  let notification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser);
-  ok(notification, "Test 1a, Should have a click-to-play notification");
-
-  await promiseForNotificationShown(notification);
-
-  is(notification.options.pluginData.size, 2,
-      "Test 1a, Should have two types of plugin in the notification");
-
-  // Work around for delayed PluginBindingAttached
-  await promiseUpdatePluginBindings(gBrowser.selectedBrowser);
-
-  is(PopupNotifications.panel.firstChild.childNodes.length, 2, "have child nodes");
-
-  let pluginItem = null;
-  for (let item of PopupNotifications.panel.firstChild.childNodes) {
-    is(item.value, "block", "Test 1a, all plugins should start out blocked");
-    if (item.action.pluginName == "Test") {
-      pluginItem = item;
-    }
-  }
-
-  // Choose "Allow now" for the test plugin
-  pluginItem.value = "allownow";
-  PopupNotifications.panel.firstChild._primaryButton.click();
-
-  pluginInfo = await promiseForPluginInfo("test", gBrowser.selectedBrowser);
-  ok(pluginInfo.activated, "plugin should be activated");
-
-  notification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser);
-  ok(notification, "Test 1b, Should have a click-to-play notification");
-
-  await promiseForNotificationShown(notification);
-
-  pluginItem = null;
-  for (let item of PopupNotifications.panel.firstChild.childNodes) {
-    if (item.action.pluginName == "Test") {
-      is(item.value, "allownow", "Test 1b, Test plugin should now be set to 'Allow now'");
-    } else {
-      is(item.value, "block", "Test 1b, Second Test plugin should still be blocked");
-      pluginItem = item;
-    }
-  }
-
-  // Choose "Allow and remember" for the Second Test plugin
-  pluginItem.value = "allowalways";
-  PopupNotifications.panel.firstChild._primaryButton.click();
-
-  pluginInfo = await promiseForPluginInfo("secondtestA", gBrowser.selectedBrowser);
-  ok(pluginInfo.activated, "plugin should be activated");
-
-  notification = PopupNotifications.getNotification("click-to-play-plugins", gBrowser.selectedBrowser);
-  ok(notification, "Test 1c, Should have a click-to-play notification");
-
-  await promiseForNotificationShown(notification);
-
-  for (let item of PopupNotifications.panel.firstChild.childNodes) {
-    if (item.action.pluginName == "Test") {
-      is(item.value, "allownow", "Test 1c, Test plugin should be set to 'Allow now'");
-    } else {
-      is(item.value, "allowalways", "Test 1c, Second Test plugin should be set to 'Allow always'");
-    }
-  }
-});
--- a/browser/base/content/test/plugins/browser_CTP_notificationBar.js
+++ b/browser/base/content/test/plugins/browser_CTP_notificationBar.js
@@ -77,17 +77,17 @@ add_task(async function() {
 
   let pluginInfo = await promiseForPluginInfo("test");
   ok(!pluginInfo.activated, "Test 1a, plugin should not be activated");
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
-    Assert.ok(!(overlay && overlay.classList.contains("visible")),
+    Assert.ok(!overlay || !overlay.classList.contains("visible"),
       "Test 3b, overlay should be hidden.");
   });
 });
 
 add_task(async function() {
   await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_positioned.html");
 
   // Work around for delayed PluginBindingAttached
@@ -104,17 +104,17 @@ add_task(async function() {
     Assert.equal(plugin.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
       "Test 4b, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
   });
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
-    Assert.ok(!(overlay && overlay.classList.contains("visible")),
+    Assert.ok(!overlay || !overlay.classList.contains("visible"),
       "Test 4b, overlay should be hidden.");
   });
 });
 
 // Test that the notification bar is getting dismissed when directly activating plugins
 // via the doorhanger.
 
 add_task(async function() {
@@ -137,16 +137,16 @@ add_task(async function() {
   await promisePopupNotification("click-to-play-plugins");
 
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 6, Should have a click-to-play notification");
 
   // simulate "always allow"
   await promiseForNotificationShown(notification);
 
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
   await promiseForCondition(() => notificationBox.getNotificationWithValue("plugin-hidden") === null);
 
   let pluginInfo = await promiseForPluginInfo("test");
   ok(pluginInfo.activated, "Test 7, plugin should be activated");
 });
--- a/browser/base/content/test/plugins/browser_CTP_outsideScrollArea.js
+++ b/browser/base/content/test/plugins/browser_CTP_outsideScrollArea.js
@@ -52,18 +52,19 @@ add_task(async function() {
   await promiseUpdatePluginBindings(gTestBrowser);
 
   await promisePopupNotification("click-to-play-plugins");
 
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let plugin = content.document.getElementById("test");
     let doc = content.document;
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
-    Assert.ok(overlay && overlay.classList.contains("visible"),
-      "Test 2, overlay should be visible.");
+    Assert.ok(overlay && overlay.classList.contains("visible") &&
+              !overlay.classList.contains("minimal"),
+              "Test 2, overlay should be visible.");
   });
 });
 
 add_task(async function() {
   await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_outsideScrollArea.html");
 
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let doc = content.document;
@@ -81,18 +82,19 @@ add_task(async function() {
   await promiseUpdatePluginBindings(gTestBrowser);
 
   await promisePopupNotification("click-to-play-plugins");
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let plugin = content.document.getElementById("test");
     let doc = content.document;
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
-    Assert.ok(overlay && overlay.classList.contains("visible"),
-      "Test 3, overlay should be visible.");
+    Assert.ok(overlay && overlay.classList.contains("visible") &&
+              !overlay.classList.contains("minimal"),
+              "Test 3, overlay should be visible.");
   });
 });
 
 add_task(async function() {
   await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_outsideScrollArea.html");
 
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let doc = content.document;
@@ -109,12 +111,12 @@ add_task(async function() {
   // Work around for delayed PluginBindingAttached
   await promiseUpdatePluginBindings(gTestBrowser);
 
   await promisePopupNotification("click-to-play-plugins");
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let plugin = content.document.getElementById("test");
     let doc = content.document;
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
-    Assert.ok(!(overlay && overlay.classList.contains("visible")),
+    Assert.ok(!overlay || !overlay.classList.contains("visible"),
       "Test 4, overlay should be hidden.");
   });
 });
--- a/browser/base/content/test/plugins/browser_CTP_resize.js
+++ b/browser/base/content/test/plugins/browser_CTP_resize.js
@@ -41,17 +41,17 @@ add_task(async function() {
 add_task(async function() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 2, Should have a click-to-play notification");
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
-    Assert.ok(!(overlay && overlay.classList.contains("visible")),
+    Assert.ok(!overlay || overlay.classList.contains("minimal"),
       "Test 2, overlay should be hidden.");
   });
 });
 
 add_task(async function() {
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let plugin = content.document.getElementById("test");
     plugin.style.width = "300px";
@@ -59,17 +59,17 @@ add_task(async function() {
 
   // Work around for delayed PluginBindingAttached
   await promiseUpdatePluginBindings(gTestBrowser);
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
-    Assert.ok(!(overlay && overlay.classList.contains("visible")),
+    Assert.ok(!overlay || overlay.classList.contains("minimal"),
       "Test 3, overlay should be hidden.");
   });
 });
 
 
 add_task(async function() {
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let plugin = content.document.getElementById("test");
@@ -99,17 +99,17 @@ add_task(async function() {
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     content.document.getElementById("test").clientTop;
   });
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main");
-    Assert.ok(!(overlay && overlay.classList.contains("visible")),
+    Assert.ok(!overlay || overlay.classList.contains("minimal"),
       "Test 5, overlay should be hidden.");
   });
 });
 
 add_task(async function() {
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let plugin = content.document.getElementById("test");
     plugin.style.height = "300px";
--- a/browser/base/content/test/plugins/browser_blocking.js
+++ b/browser/base/content/test/plugins/browser_blocking.js
@@ -35,41 +35,16 @@ add_task(async function() {
 
   // Make sure the blocklist service(s) are running
   Components.classes["@mozilla.org/extensions/blocklist;1"]
             .getService(Components.interfaces.nsIBlocklistService);
   let exmsg = await promiseInitContentBlocklistSvc(gBrowser.selectedBrowser);
   ok(!exmsg, "exception: " + exmsg);
 });
 
-add_task(async function() {
-  // enable hard blocklisting for the next test
-  await asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginHard.xml", gTestBrowser);
-
-  await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html");
-
-  // Work around for delayed PluginBindingAttached
-  await promiseUpdatePluginBindings(gTestBrowser);
-
-  await promisePopupNotification("click-to-play-plugins");
-
-  let notification = PopupNotifications.getNotification("click-to-play-plugins");
-  ok(notification.dismissed, "Test 5: The plugin notification should be dismissed by default");
-
-  await promiseForNotificationShown(notification);
-
-  let pluginInfo = await promiseForPluginInfo("test");
-  is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED, "Test 5, plugin fallback type should be PLUGIN_BLOCKLISTED");
-
-  is(notification.options.pluginData.size, 1, "Test 5: Only the blocked plugin should be present in the notification");
-  ok(PopupNotifications.panel.firstChild._buttonContainer.hidden, "Part 5: The blocked plugins notification should not have any buttons visible.");
-
-  await asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser);
-});
-
 // Tests a vulnerable, updatable plugin
 
 add_task(async function() {
   // enable hard blocklisting of test
   await asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginVulnerableUpdatable.xml", gTestBrowser);
 
   await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html");
 
@@ -158,20 +133,20 @@ add_task(async function() {
     Assert.ok(overlay && overlay.classList.contains("visible"),
       "Test 18c, Plugin overlay should exist, not be hidden");
 
     let updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink");
     Assert.ok(updateLink && updateLink.style.display != "block",
       "Test 18c, Plugin should not have an update link");
   });
 
-  // check that click "Always allow" works with blocked plugins
+  // check that click "Allow" works with blocked plugins
   await promiseForNotificationShown(notification);
 
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   pluginInfo = await promiseForPluginInfo("test");
   is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE,
      "Test 18c, plugin fallback type should be PLUGIN_VULNERABLE_NO_UPDATE");
   ok(pluginInfo.activated, "Test 18c, Plugin should be activated");
   let enabledState = getTestPluginEnabledState();
   ok(enabledState, "Test 18c, Plugin enabled state should be STATE_CLICKTOPLAY");
 });
@@ -249,20 +224,20 @@ add_task(async function() {
   ok(notification, "Test 24a, Should have a click-to-play notification");
 
   // Plugin should start as CTP
   let pluginInfo = await promiseForPluginInfo("test");
   is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
      "Test 24a, plugin fallback type should be PLUGIN_CLICK_TO_PLAY");
   ok(!pluginInfo.activated, "Test 24a, Plugin should not be active.");
 
-  // simulate "always allow"
+  // simulate "allow"
   await promiseForNotificationShown(notification);
 
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   pluginInfo = await promiseForPluginInfo("test");
   ok(pluginInfo.activated, "Test 24a, Plugin should be active.");
 
   await asyncSetAndUpdateBlocklist(gTestRoot + "blockPluginVulnerableUpdatable.xml", gTestBrowser);
 });
 
 // the plugin is now blocklisted, so it should not automatically load
@@ -275,20 +250,20 @@ add_task(async function() {
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 24b, Should have a click-to-play notification");
 
   let pluginInfo = await promiseForPluginInfo("test");
   is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE,
      "Test 24b, plugin fallback type should be PLUGIN_VULNERABLE_UPDATABLE");
   ok(!pluginInfo.activated, "Test 24b, Plugin should not be active.");
 
-  // simulate "always allow"
+  // simulate "allow"
   await promiseForNotificationShown(notification);
 
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   pluginInfo = await promiseForPluginInfo("test");
   ok(pluginInfo.activated, "Test 24b, Plugin should be active.");
 
   clearAllPluginPermissions();
 
   await asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser);
 });
@@ -332,18 +307,10 @@ add_task(async function() {
   is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED,
      "Test 26, plugin fallback type should be PLUGIN_BLOCKLISTED");
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let plugin = content.document.getElementById("test");
     let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     Assert.ok(!objLoadingContent.activated, "Plugin should not be activated.");
   });
-
-  const testUrl = "http://test.url.com/";
-
-  let firstPanelChild = PopupNotifications.panel.firstChild;
-  let infoLink = document.getAnonymousElementByAttribute(firstPanelChild, "anonid",
-    "click-to-play-plugins-notification-link");
-  is(infoLink.href, testUrl,
-    "Test 26, the notification URL needs to match the infoURL from the blocklist file.");
 });
 
--- a/browser/base/content/test/plugins/browser_bug743421.js
+++ b/browser/base/content/test/plugins/browser_bug743421.js
@@ -56,17 +56,17 @@ add_task(async function() {
     Assert.ok(!objLoadingContent.activated, "Test 1b, Plugin should not be activated");
   });
 
   // Click the activate button on doorhanger to make sure it works
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
 
   await promiseForNotificationShown(notification);
 
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   await ContentTask.spawn(gTestBrowser, {}, async function() {
     let plugin = content.document.getElementsByTagName("embed")[0];
     let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     Assert.ok(objLoadingContent.activated, "Test 1b, Plugin should be activated");
   });
 });
 
--- a/browser/base/content/test/plugins/browser_bug787619.js
+++ b/browser/base/content/test/plugins/browser_bug787619.js
@@ -50,16 +50,16 @@ add_task(async function() {
 
   // check plugin state
   pluginInfo = await promiseForPluginInfo("plugin");
   ok(!pluginInfo.activated, "1b plugin should not be activated");
 
   let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed &&
     PopupNotifications.panel.firstChild;
   await promiseForCondition(condition);
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   // check plugin state
   pluginInfo = await promiseForPluginInfo("plugin");
   ok(pluginInfo.activated, "plugin should be activated");
 
   is(gWrapperClickCount, 0, "wrapper should not have received any clicks");
 });
--- a/browser/base/content/test/plugins/browser_pluginnotification.js
+++ b/browser/base/content/test/plugins/browser_pluginnotification.js
@@ -60,34 +60,39 @@ add_task(async function() {
   // Work around for delayed PluginBindingAttached
   await promiseUpdatePluginBindings(gTestBrowser);
 
   await promisePopupNotification("click-to-play-plugins");
 
   let pluginInfo = await promiseForPluginInfo("test");
   ok(!pluginInfo.activated, "Plugin should not be activated");
 
-  // Simulate clicking the "Allow Now" button.
+  // Simulate clicking the "Allow" button.
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
 
   await promiseForNotificationShown(notification);
 
-  PopupNotifications.panel.firstChild._secondaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   pluginInfo = await promiseForPluginInfo("test");
   ok(pluginInfo.activated, "Plugin should be activated");
 
   // Simulate clicking the "Block" button.
   await promiseForNotificationShown(notification);
 
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.secondaryButton.click();
 
   pluginInfo = await promiseForPluginInfo("test");
   ok(!pluginInfo.activated, "Plugin should not be activated");
 
+  let browserLoaded = BrowserTestUtils.browserLoaded(gTestBrowser);
+  gTestBrowser.reload();
+  await browserLoaded;
+  notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+
   // Simulate clicking the overlay
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let bounds = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
     let left = (bounds.left + bounds.right) / 2;
     let top = (bounds.top + bounds.bottom) / 2;
     let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
@@ -132,22 +137,22 @@ add_task(async function() {
   // Work around for delayed PluginBindingAttached
   await promiseUpdatePluginBindings(gTestBrowser);
 
   await promisePopupNotification("click-to-play-plugins");
 
   let pluginInfo = await promiseForPluginInfo("test");
   ok(!pluginInfo.activated, "Test 12a, Plugin should not be activated");
 
-  // Simulate clicking the "Allow Always" button.
+  // Simulate clicking the "Allow" button.
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
 
   await promiseForNotificationShown(notification);
 
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   pluginInfo = await promiseForPluginInfo("test");
   ok(pluginInfo.activated, "Test 12a, Plugin should be activated");
 });
 
 // Test that the "Always" permission, when set for just the Test plugin,
 // does not also allow the Second Test plugin.
 add_task(async function() {
@@ -291,17 +296,17 @@ add_task(async function() {
                        .getInterface(Components.interfaces.nsIDOMWindowUtils);
     utils.sendMouseEvent("mousedown", 50, 50, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", 50, 50, 0, 1, 0, false, 0, 0);
   });
 
   let condition = () => !PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser).dismissed &&
     PopupNotifications.panel.firstChild;
   await promiseForCondition(condition);
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   pluginInfo = await promiseForPluginInfo("test");
   ok(pluginInfo.activated, "Test 19e, Plugin should not be activated");
 
   clearAllPluginPermissions();
 });
 
 // Tests that a plugin in a div that goes from style="display: none" to
@@ -372,168 +377,32 @@ add_task(async function() {
     let utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                        .getInterface(Components.interfaces.nsIDOMWindowUtils);
     utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
     utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
   });
 
   let condition = () => !notification.dismissed && !!PopupNotifications.panel.firstChild;
   await promiseForCondition(condition);
-  PopupNotifications.panel.firstChild._primaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   pluginInfo = await promiseForPluginInfo("test");
   ok(pluginInfo.activated, "Test 20c, plugin should be activated");
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let doc = content.document;
     let plugin = doc.getElementById("test");
     let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
     Assert.ok(overlayRect.width == 0 && overlayRect.height == 0,
       "Test 20c, plugin should have overlay dims of 0px");
   });
 
   clearAllPluginPermissions();
 });
 
-// Test having multiple different types of plugin on one page
-add_task(async function() {
-  // contains three plugins, application/x-test, application/x-second-test x 2
-  await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_two_types.html");
-
-  // Work around for delayed PluginBindingAttached
-  await promiseUpdatePluginBindings(gTestBrowser);
-
-  let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(notification, "Test 21a, Should have a click-to-play notification");
-
-  // confirm all three are blocked by ctp at this point
-  let ids = ["test", "secondtestA", "secondtestB"];
-  for (let id of ids) {
-    await ContentTask.spawn(gTestBrowser, { id }, async function(args) {
-      let doc = content.document;
-      let plugin = doc.getElementById(args.id);
-      let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
-      Assert.ok(overlayRect.width == 200 && overlayRect.height == 200,
-        "Test 21a, plugin " + args.id + " should have click-to-play overlay with dims");
-    });
-
-    let pluginInfo = await promiseForPluginInfo(id);
-    ok(!pluginInfo.activated, "Test 21a, Plugin with id=" + id + " should not be activated");
-  }
-
-  notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(notification, "Test 21a, Should have a click-to-play notification");
-
-  // we have to actually show the panel to get the bindings to instantiate
-  await promiseForNotificationShown(notification);
-
-  is(notification.options.pluginData.size, 2, "Test 21a, Should have two types of plugin in the notification");
-
-  let centerAction = null;
-  for (let action of notification.options.pluginData.values()) {
-    if (action.pluginName == "Test") {
-      centerAction = action;
-      break;
-    }
-  }
-  ok(centerAction, "Test 21b, found center action for the Test plugin");
-
-  let centerItem = null;
-  for (let item of PopupNotifications.panel.firstChild.childNodes) {
-    is(item.value, "block", "Test 21b, all plugins should start out blocked");
-    if (item.action == centerAction) {
-      centerItem = item;
-      break;
-    }
-  }
-  ok(centerItem, "Test 21b, found center item for the Test plugin");
-
-  // Select the allow now option in the select drop down for Test Plugin
-  centerItem.value = "allownow";
-
-  // "click" the button to activate the Test plugin
-  PopupNotifications.panel.firstChild._primaryButton.click();
-
-  let pluginInfo = await promiseForPluginInfo("test");
-  ok(pluginInfo.activated, "Test 21b, plugin should be activated");
-
-  notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(notification, "Test 21b, Should have a click-to-play notification");
-
-  await promiseForNotificationShown(notification);
-
-  ok(notification.options.pluginData.size == 2, "Test 21c, Should have one type of plugin in the notification");
-
-  await ContentTask.spawn(gTestBrowser, null, async function() {
-    let doc = content.document;
-    let plugin = doc.getElementById("test");
-    let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
-    Assert.ok(overlayRect.width == 0 && overlayRect.height == 0,
-      "Test 21c, plugin should have overlay dims of 0px");
-  });
-
-  ids = ["secondtestA", "secondtestB"];
-  for (let id of ids) {
-    await ContentTask.spawn(gTestBrowser, { id }, async function(args) {
-      let doc = content.document;
-      let plugin = doc.getElementById(args.id);
-      let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
-      Assert.ok(overlayRect.width == 200 && overlayRect.height == 200,
-        "Test 21c, plugin " + args.id + " should have click-to-play overlay with zero dims");
-    });
-
-    let pluginInfoTmp = await promiseForPluginInfo(id);
-    ok(!pluginInfoTmp.activated, "Test 21c, Plugin with id=" + id + " should not be activated");
-  }
-
-  centerAction = null;
-  for (let action of notification.options.pluginData.values()) {
-    if (action.pluginName == "Second Test") {
-      centerAction = action;
-      break;
-    }
-  }
-  ok(centerAction, "Test 21d, found center action for the Second Test plugin");
-
-  centerItem = null;
-  for (let item of PopupNotifications.panel.firstChild.childNodes) {
-    if (item.action == centerAction) {
-      is(item.value, "block", "Test 21d, test plugin 2 should start blocked");
-      centerItem = item;
-      break;
-    } else {
-      is(item.value, "allownow", "Test 21d, test plugin should be enabled");
-    }
-  }
-  ok(centerItem, "Test 21d, found center item for the Second Test plugin");
-
-  // Select the allow now option in the select drop down for Second Test Plguins
-  centerItem.value = "allownow";
-
-  // "click" the button to activate the Second Test plugins
-  PopupNotifications.panel.firstChild._primaryButton.click();
-
-  notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(notification, "Test 21d, Should have a click-to-play notification");
-
-  ids = ["test", "secondtestA", "secondtestB"];
-  for (let id of ids) {
-    await ContentTask.spawn(gTestBrowser, { id }, async function(args) {
-      let doc = content.document;
-      let plugin = doc.getElementById(args.id);
-      let overlayRect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
-      Assert.ok(overlayRect.width == 0 && overlayRect.height == 0,
-        "Test 21d, plugin " + args.id + " should have click-to-play overlay with zero dims");
-    });
-
-    let pluginInfoTmp = await promiseForPluginInfo(id);
-    ok(pluginInfoTmp.activated, "Test 21d, Plugin with id=" + id + " should not be activated");
-  }
-});
-
 // Tests that a click-to-play plugin resets its activated state when changing types
 add_task(async function() {
   clearAllPluginPermissions();
 
   updateAllTestPlugins(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
 
   await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_test.html");
 
@@ -608,17 +477,9 @@ add_task(async function() {
 
   // Since the plugin notification is dismissed by default, reshow it.
   await promiseForNotificationShown(notification);
 
   let pluginInfo = await promiseForPluginInfo("test");
   is(pluginInfo.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED,
      "Test 26, plugin fallback type should be PLUGIN_BLOCKLISTED");
   ok(!pluginInfo.activated, "Plugin should be activated.");
-
-  const testUrl = "http://test.url.com/";
-
-  let firstPanelChild = PopupNotifications.panel.firstChild;
-  let infoLink = document.getAnonymousElementByAttribute(firstPanelChild, "anonid",
-    "click-to-play-plugins-notification-link");
-  is(infoLink.href, testUrl,
-    "Test 26, the notification URL needs to match the infoURL from the blocklist file.");
 });
deleted file mode 100644
--- a/browser/base/content/test/plugins/browser_plugins_added_dynamically.js
+++ /dev/null
@@ -1,137 +0,0 @@
-var rootDir = getRootDirectory(gTestPath);
-const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://mochi.test:8888/");
-var gPluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
-
-var gTestBrowser = null;
-
-add_task(async function() {
-  registerCleanupFunction(async function() {
-    clearAllPluginPermissions();
-    Services.prefs.clearUserPref("plugins.click_to_play");
-    setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
-    setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in");
-    await asyncSetAndUpdateBlocklist(gTestRoot + "blockNoPlugins.xml", gTestBrowser);
-    resetBlocklist();
-    gBrowser.removeCurrentTab();
-    window.focus();
-    gTestBrowser = null;
-  });
-});
-
-// "Activate" of a given type -> plugins of that type dynamically added should
-// automatically play.
-add_task(async function() {
-  let newTab = BrowserTestUtils.addTab(gBrowser);
-  gBrowser.selectedTab = newTab;
-  gTestBrowser = gBrowser.selectedBrowser;
-
-  Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
-  Services.prefs.setBoolPref("plugins.click_to_play", true);
-
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in");
-  setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in");
-});
-
-add_task(async function() {
-  await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_add_dynamically.html");
-
-  let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(!notification, "Test 1a, Should not have a click-to-play notification");
-
-  // Add a plugin of type test
-  await ContentTask.spawn(gTestBrowser, {}, async function() {
-    new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin("pluginone", "application/x-test"));
-  });
-
-  await promisePopupNotification("click-to-play-plugins");
-
-  notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(notification, "Test 1a, Should not have a click-to-play notification");
-
-  await promiseForNotificationShown(notification);
-
-  let centerAction = null;
-  for (let action of notification.options.pluginData.values()) {
-    if (action.pluginName == "Test") {
-      centerAction = action;
-      break;
-    }
-  }
-  ok(centerAction, "Test 2, found center action for the Test plugin");
-
-  let centerItem = null;
-  for (let item of PopupNotifications.panel.firstChild.childNodes) {
-    is(item.value, "block", "Test 3, all plugins should start out blocked");
-    if (item.action == centerAction) {
-      centerItem = item;
-      break;
-    }
-  }
-  ok(centerItem, "Test 4, found center item for the Test plugin");
-
-  // Select the allow now option in the select drop down for Test Plugin
-  centerItem.value = "allownow";
-
-  // "click" the button to activate the Test plugin
-  PopupNotifications.panel.firstChild._primaryButton.click();
-
-  let pluginInfo = await promiseForPluginInfo("pluginone");
-  ok(pluginInfo.activated, "Test 5, plugin should be activated");
-
-  // Add another plugin of type test
-  await ContentTask.spawn(gTestBrowser, {}, async function() {
-    new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin("plugintwo", "application/x-test"));
-  });
-
-  pluginInfo = await promiseForPluginInfo("plugintwo");
-  ok(pluginInfo.activated, "Test 6, plugins should be activated");
-});
-
-// "Activate" of a given type -> plugins of other types dynamically added
-// should not automatically play.
-add_task(async function() {
-  clearAllPluginPermissions();
-
-  await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_add_dynamically.html");
-
-  let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(!notification, "Test 7, Should not have a click-to-play notification");
-
-  // Add a plugin of type test
-  await ContentTask.spawn(gTestBrowser, {}, async function() {
-    new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin("pluginone", "application/x-test"));
-  });
-
-  await promisePopupNotification("click-to-play-plugins");
-
-  notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  ok(notification, "Test 8, Should not have a click-to-play notification");
-
-  await promiseForNotificationShown(notification);
-
-  is(notification.options.pluginData.size, 1, "Should be one plugin action");
-
-  let pluginInfo = await promiseForPluginInfo("pluginone");
-  ok(!pluginInfo.activated, "Test 8, test plugin should be activated");
-
-  let condition = () => !notification.dismissed &&
-    PopupNotifications.panel.firstChild;
-  await promiseForCondition(condition);
-
-  // "click" the button to activate the Test plugin
-  PopupNotifications.panel.firstChild._primaryButton.click();
-
-  pluginInfo = await promiseForPluginInfo("pluginone");
-  ok(pluginInfo.activated, "Test 9, test plugin should be activated");
-
-  await ContentTask.spawn(gTestBrowser, {}, async function() {
-    new XPCNativeWrapper(XPCNativeWrapper.unwrap(content).addPlugin("plugintwo", "application/x-second-test"));
-  });
-
-  await promisePopupNotification("click-to-play-plugins");
-
-  pluginInfo = await promiseForPluginInfo("pluginone");
-  ok(pluginInfo.activated, "Test 10, plugins should be activated");
-  pluginInfo = await promiseForPluginInfo("plugintwo");
-  ok(!pluginInfo.activated, "Test 11, plugins should be activated");
-});
--- a/browser/base/content/test/plugins/browser_private_clicktoplay.js
+++ b/browser/base/content/test/plugins/browser_private_clicktoplay.js
@@ -62,20 +62,17 @@ add_task(async function test1b() {
   });
 
   // Check the button status
   let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel,
                                                    "Shown");
   popupNotification.reshow();
 
   await promiseShown;
-  let button1 = gPrivateWindow.PopupNotifications.panel.firstChild._primaryButton;
-  let button2 = gPrivateWindow.PopupNotifications.panel.firstChild._secondaryButton;
-  is(button1.getAttribute("action"), "_singleActivateNow", "Test 1b, Blocked plugin in private window should have a activate now button");
-  ok(button2.hidden, "Test 1b, Blocked plugin in a private window should not have a secondary button");
+  is(gPrivateWindow.PopupNotifications.panel.firstChild.checkbox.hidden, true, "'Remember' checkbox should be hidden in private windows")
 
   gPrivateWindow.close();
   BrowserTestUtils.loadURI(gTestBrowser, gHttpTestRoot + "plugin_test.html");
   await BrowserTestUtils.browserLoaded(gTestBrowser);
 });
 
 add_task(async function test2a() {
   // enable test plugin on this site
@@ -89,17 +86,17 @@ add_task(async function test2a() {
   });
 
   // Simulate clicking the "Allow Now" button.
   let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
                                                    "Shown");
   popupNotification.reshow();
   await promiseShown;
 
-  PopupNotifications.panel.firstChild._secondaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let plugin = content.document.getElementById("test");
     let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     let condition = () => objLoadingContent.activated;
     await ContentTaskUtils.waitForCondition(condition, "Test 2a, Waited too long for plugin to activate");
   });
 });
@@ -118,18 +115,20 @@ add_task(async function test2c() {
     ok(objLoadingContent.activated, "Test 2c, Plugin should be activated");
   });
 
   // Check the button status
   let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel,
                                                    "Shown");
   popupNotification.reshow();
   await promiseShown;
-  let buttonContainer = gPrivateWindow.PopupNotifications.panel.firstChild._buttonContainer;
-  ok(buttonContainer.hidden, "Test 2c, Activated plugin in a private window should not have visible buttons");
+  is(gPrivateWindow.PopupNotifications.panel.firstChild.secondaryButton.hidden, true,
+     "Test 2c, Activated plugin in a private window should not have visible 'Block' button.");
+  is(gPrivateWindow.PopupNotifications.panel.firstChild.checkbox.hidden, true,
+     "Test 2c, Activated plugin in a private window should not have visible 'Remember' checkbox.");
 
   clearAllPluginPermissions();
   gPrivateWindow.close();
 
   BrowserTestUtils.loadURI(gTestBrowser, gHttpTestRoot + "plugin_test.html");
   await BrowserTestUtils.browserLoaded(gTestBrowser);
 });
 
@@ -139,22 +138,22 @@ add_task(async function test3a() {
   ok(popupNotification, "Test 3a, Should have a click-to-play notification");
 
   await ContentTask.spawn(gTestBrowser, null, function() {
     let plugin = content.document.getElementById("test");
     let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     ok(!objLoadingContent.activated, "Test 3a, Plugin should not be activated");
   });
 
-  // Simulate clicking the "Allow Always" button.
+  // Simulate clicking the "Allow" button.
   let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
                                                    "Shown");
   popupNotification.reshow();
   await promiseShown;
-  PopupNotifications.panel.firstChild._secondaryButton.click();
+  PopupNotifications.panel.firstChild.button.click();
 
   await ContentTask.spawn(gTestBrowser, null, async function() {
     let plugin = content.document.getElementById("test");
     let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     let condition = () => objLoadingContent.activated;
     await ContentTaskUtils.waitForCondition(condition, "Test 3a, Waited too long for plugin to activate");
   });
 });
@@ -167,18 +166,20 @@ add_task(async function test3c() {
   let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser);
   ok(popupNotification, "Test 3c, Should have a click-to-play notification");
 
   // Check the button status
   let promiseShown = BrowserTestUtils.waitForEvent(gPrivateWindow.PopupNotifications.panel,
                                                    "Shown");
   popupNotification.reshow();
   await promiseShown;
-  let buttonContainer = gPrivateWindow.PopupNotifications.panel.firstChild._buttonContainer;
-  ok(buttonContainer.hidden, "Test 3c, Activated plugin in a private window should not have visible buttons");
+  is(gPrivateWindow.PopupNotifications.panel.firstChild.secondaryButton.hidden, true,
+     "Test 2c, Activated plugin in a private window should not have visible 'Block' button.");
+  is(gPrivateWindow.PopupNotifications.panel.firstChild.checkbox.hidden, true,
+     "Test 2c, Activated plugin in a private window should not have visible 'Remember' checkbox.");
 
   BrowserTestUtils.loadURI(gPrivateBrowser, gHttpTestRoot + "plugin_two_types.html");
   await BrowserTestUtils.browserLoaded(gPrivateBrowser);
 });
 
 add_task(async function test3d() {
   let popupNotification = gPrivateWindow.PopupNotifications.getNotification("click-to-play-plugins", gPrivateBrowser);
   ok(popupNotification, "Test 3d, Should have a click-to-play notification");
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -2543,523 +2543,9 @@ file, You can obtain one at http://mozil
 
       <method name="onDownloadEnded">
         <body><![CDATA[
           this.updateProgress();
         ]]></body>
       </method>
     </implementation>
   </binding>
-
-  <binding id="plugin-popupnotification-center-item">
-    <content align="center">
-      <xul:vbox pack="center" anonid="itemBox" class="itemBox">
-        <xul:description anonid="center-item-label" class="center-item-label" />
-        <xul:hbox flex="1" pack="start" align="center" anonid="center-item-warning">
-          <xul:image anonid="center-item-warning-icon" class="center-item-warning-icon"/>
-          <xul:label anonid="center-item-warning-label"/>
-          <xul:label anonid="center-item-link" value="&checkForUpdates;" class="text-link"/>
-        </xul:hbox>
-      </xul:vbox>
-      <xul:vbox pack="center">
-        <xul:menulist class="center-item-menulist"
-                      anonid="center-item-menulist">
-          <xul:menupopup>
-            <xul:menuitem anonid="allownow" value="allownow"
-                          label="&pluginActivateNow.label;" />
-            <xul:menuitem anonid="allowalways" value="allowalways"
-                          label="&pluginActivateAlways.label;" />
-            <xul:menuitem anonid="block" value="block"
-                          label="&pluginBlockNow.label;" />
-          </xul:menupopup>
-        </xul:menulist>
-      </xul:vbox>
-    </content>
-    <resources>
-      <stylesheet src="chrome://global/skin/notification.css"/>
-    </resources>
-    <implementation>
-      <constructor><![CDATA[
-        document.getAnonymousElementByAttribute(this, "anonid", "center-item-label").value = this.action.pluginName;
-
-        let curState = "block";
-        if (this.action.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
-          if (this.action.pluginPermissionType == Ci.nsIPermissionManager.EXPIRE_SESSION) {
-            curState = "allownow";
-          } else {
-            curState = "allowalways";
-          }
-        }
-        document.getAnonymousElementByAttribute(this, "anonid", "center-item-menulist").value = curState;
-
-        let warningString = "";
-        let linkString = "";
-
-        let link = document.getAnonymousElementByAttribute(this, "anonid", "center-item-link");
-
-        let url;
-        let linkHandler;
-
-        if (this.action.pluginTag.enabledState == Ci.nsIPluginTag.STATE_DISABLED) {
-          document.getAnonymousElementByAttribute(this, "anonid", "center-item-menulist").hidden = true;
-          warningString = gNavigatorBundle.getString("pluginActivateDisabled.label");
-          linkString = gNavigatorBundle.getString("pluginActivateDisabled.manage");
-          linkHandler = function(event) {
-            event.preventDefault();
-            gPluginHandler.managePlugins();
-          };
-          document.getAnonymousElementByAttribute(this, "anonid", "center-item-warning-icon").hidden = true;
-        } else {
-          url = this.action.detailsLink;
-
-          switch (this.action.blocklistState) {
-          case Ci.nsIBlocklistService.STATE_NOT_BLOCKED:
-            document.getAnonymousElementByAttribute(this, "anonid", "center-item-warning").hidden = true;
-            break;
-          case Ci.nsIBlocklistService.STATE_BLOCKED:
-            document.getAnonymousElementByAttribute(this, "anonid", "center-item-menulist").hidden = true;
-            warningString = gNavigatorBundle.getString("pluginActivateBlocked.label");
-            linkString = gNavigatorBundle.getString("pluginActivate.learnMore");
-            break;
-          case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE:
-            warningString = gNavigatorBundle.getString("pluginActivateOutdated.label");
-            linkString = gNavigatorBundle.getString("pluginActivate.updateLabel");
-            break;
-          case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE:
-            warningString = gNavigatorBundle.getString("pluginActivateVulnerable.label");
-            linkString = gNavigatorBundle.getString("pluginActivate.riskLabel");
-            break;
-          }
-        }
-        document.getAnonymousElementByAttribute(this, "anonid", "center-item-warning-label").value = warningString;
-
-        let chromeWin = window.QueryInterface(Ci.nsIDOMChromeWindow);
-        let isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(chromeWin);
-
-        if (isWindowPrivate) {
-          // TODO: temporary compromise of hiding some privacy leaks, remove once bug 892487 is fixed
-          let allowalways = document.getAnonymousElementByAttribute(this, "anonid", "allowalways");
-          let block = document.getAnonymousElementByAttribute(this, "anonid", "block");
-          let allownow = document.getAnonymousElementByAttribute(this, "anonid", "allownow");
-
-          allowalways.hidden = curState !== "allowalways";
-          block.hidden       = curState !== "block";
-          allownow.hidden    = curState === "allowalways";
-        }
-
-        if (url || linkHandler) {
-          link.value = linkString;
-          if (url) {
-            link.href = url;
-          }
-          if (linkHandler) {
-            link.addEventListener("click", linkHandler);
-          }
-        } else {
-          link.hidden = true;
-        }
-      ]]></constructor>
-      <property name="value">
-        <getter>
-          return document.getAnonymousElementByAttribute(this, "anonid",
-                   "center-item-menulist").value;
-        </getter>
-        <setter><!-- This should be used only in automated tests -->
-          document.getAnonymousElementByAttribute(this, "anonid",
-                    "center-item-menulist").value = val;
-        </setter>
-      </property>
-    </implementation>
-  </binding>
-
-  <binding id="click-to-play-plugins-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
-    <content align="start" style="width: &pluginNotification.width;;">
-      <xul:vbox flex="1" align="stretch" class="click-to-play-plugins-notification-main-box"
-                xbl:inherits="popupid">
-        <xul:hbox class="click-to-play-plugins-notification-description-box" flex="1" align="start">
-          <xul:description class="click-to-play-plugins-outer-description" flex="1">
-            <html:span anonid="click-to-play-plugins-notification-description" />
-            <html:br/>
-            <xul:label class="text-link click-to-play-plugins-notification-link popup-notification-learnmore-link"
-                       anonid="click-to-play-plugins-notification-link" />
-          </xul:description>
-        </xul:hbox>
-        <xul:grid anonid="click-to-play-plugins-notification-center-box"
-                  class="click-to-play-plugins-notification-center-box">
-          <xul:columns>
-            <xul:column flex="1"/>
-            <xul:column/>
-          </xul:columns>
-          <xul:rows>
-            <children includes="row"/>
-            <xul:hbox pack="start" anonid="plugin-notification-showbox">
-              <xul:button label="&pluginNotification.showAll.label;"
-                          accesskey="&pluginNotification.showAll.accesskey;"
-                          class="plugin-notification-showbutton"
-                          oncommand="document.getBindingParent(this)._setState(2)"/>
-            </xul:hbox>
-          </xul:rows>
-        </xul:grid>
-        <xul:hbox anonid="button-container"
-                  class="click-to-play-plugins-notification-button-container"
-                  pack="center" align="center">
-          <xul:button anonid="primarybutton"
-                      class="click-to-play-popup-button popup-notification-button"
-                      oncommand="document.getBindingParent(this)._onButton(this)"
-                      flex="1"/>
-          <xul:button anonid="secondarybutton"
-                      default="true"
-                      highlight="true"
-                      class="click-to-play-popup-button popup-notification-button"
-                      oncommand="document.getBindingParent(this)._onButton(this);"
-                      flex="1"/>
-        </xul:hbox>
-        <xul:box hidden="true">
-          <children/>
-        </xul:box>
-      </xul:vbox>
-    </content>
-    <resources>
-      <stylesheet src="chrome://global/skin/notification.css"/>
-    </resources>
-    <implementation>
-      <field name="_states">
-        ({SINGLE: 0, MULTI_COLLAPSED: 1, MULTI_EXPANDED: 2})
-      </field>
-      <field name="_primaryButton">
-        document.getAnonymousElementByAttribute(this, "anonid", "primarybutton");
-      </field>
-      <field name="_secondaryButton">
-        document.getAnonymousElementByAttribute(this, "anonid", "secondarybutton")
-      </field>
-      <field name="_buttonContainer">
-        document.getAnonymousElementByAttribute(this, "anonid", "button-container")
-      </field>
-      <field name="_brandShortName">
-        document.getElementById("bundle_brand").getString("brandShortName")
-      </field>
-      <field name="_items">[]</field>
-      <constructor><![CDATA[
-        const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-        let sortedActions = [];
-        for (let action of this.notification.options.pluginData.values()) {
-          sortedActions.push(action);
-        }
-        sortedActions.sort((a, b) => a.pluginName.localeCompare(b.pluginName));
-
-        for (let action of sortedActions) {
-          let item = document.createElementNS(XUL_NS, "row");
-          item.setAttribute("class", "plugin-popupnotification-centeritem");
-          item.action = action;
-          this.appendChild(item);
-          this._items.push(item);
-        }
-        switch (this._items.length) {
-          case 0:
-            PopupNotifications._dismiss();
-            break;
-          case 1:
-            this._setState(this._states.SINGLE);
-            break;
-          default:
-            if (this.notification.options.primaryPlugin) {
-              this._setState(this._states.MULTI_COLLAPSED);
-            } else {
-              this._setState(this._states.MULTI_EXPANDED);
-            }
-        }
-      ]]></constructor>
-      <method name="_setState">
-        <parameter name="state" />
-        <body><![CDATA[
-          var grid = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-center-box");
-
-          if (this._states.SINGLE == state) {
-            grid.hidden = true;
-            this._setupSingleState();
-            return;
-          }
-
-          let prePath = this.notification.options.principal.URI.prePath;
-          this._setupDescription("pluginActivateMultiple.message", null, prePath);
-
-          var showBox = document.getAnonymousElementByAttribute(this, "anonid", "plugin-notification-showbox");
-
-          var dialogStrings = Services.strings.createBundle("chrome://global/locale/dialog.properties");
-          this._primaryButton.label = dialogStrings.GetStringFromName("button-accept");
-          this._primaryButton.setAttribute("default", "true");
-
-          this._secondaryButton.label = dialogStrings.GetStringFromName("button-cancel");
-          this._primaryButton.setAttribute("action", "_multiAccept");
-          this._secondaryButton.setAttribute("action", "_cancel");
-
-          grid.hidden = false;
-
-          if (this._states.MULTI_COLLAPSED == state) {
-            for (let child of this.childNodes) {
-              if (child.tagName != "row") {
-                continue;
-              }
-              child.hidden = this.notification.options.primaryPlugin !=
-                             child.action.permissionString;
-            }
-            showBox.hidden = false;
-          } else {
-            for (let child of this.childNodes) {
-              if (child.tagName != "row") {
-                continue;
-              }
-              child.hidden = false;
-            }
-            showBox.hidden = true;
-          }
-          this._setupLink(null);
-        ]]></body>
-      </method>
-      <method name="_setupSingleState">
-        <body><![CDATA[
-          var action = this._items[0].action;
-          var prePath = action.pluginPermissionPrePath;
-          let chromeWin = window.QueryInterface(Ci.nsIDOMChromeWindow);
-          let isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(chromeWin);
-
-          let label, linkLabel, button1, button2;
-
-          if (action.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
-            button1 = {
-              label: "pluginBlockNow.label",
-              accesskey: "pluginBlockNow.accesskey",
-              action: "_singleBlock"
-            };
-            button2 = {
-              label: "pluginContinue.label",
-              accesskey: "pluginContinue.accesskey",
-              action: "_singleContinue",
-              default: true
-            };
-            switch (action.blocklistState) {
-            case Ci.nsIBlocklistService.STATE_NOT_BLOCKED:
-              label = "pluginEnabled.message";
-              linkLabel = "pluginActivate.learnMore";
-              break;
-
-            case Ci.nsIBlocklistService.STATE_BLOCKED:
-              Cu.reportError(Error("Cannot happen!"));
-              break;
-
-            case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE:
-              label = "pluginEnabledOutdated.message";
-              linkLabel = "pluginActivate.updateLabel";
-              break;
-
-            case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE:
-              label = "pluginEnabledVulnerable.message";
-              linkLabel = "pluginActivate.riskLabel"
-              break;
-
-            default:
-              Cu.reportError(Error("Unexpected blocklist state"));
-            }
-
-            // TODO: temporary compromise, remove this once bug 892487 is fixed
-            if (isWindowPrivate) {
-              this._buttonContainer.hidden = true;
-            }
-          } else if (action.pluginTag.enabledState == Ci.nsIPluginTag.STATE_DISABLED) {
-            let linkElement =
-              document.getAnonymousElementByAttribute(
-                         this, "anonid", "click-to-play-plugins-notification-link");
-            linkElement.textContent = gNavigatorBundle.getString("pluginActivateDisabled.manage");
-            linkElement.setAttribute("onclick", "gPluginHandler.managePlugins()");
-
-            let descElement = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description");
-            descElement.textContent = gNavigatorBundle.getFormattedString(
-              "pluginActivateDisabled.message", [action.pluginName, this._brandShortName]) + " ";
-            this._buttonContainer.hidden = true;
-            return;
-          } else if (action.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) {
-            let descElement = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description");
-            descElement.textContent = gNavigatorBundle.getFormattedString(
-              "pluginActivateBlocked.message", [action.pluginName, this._brandShortName]) + " ";
-            this._setupLink("pluginActivate.learnMore", action.detailsLink);
-            this._buttonContainer.hidden = true;
-            return;
-          } else {
-            button1 = {
-              label: "pluginActivateNow.label",
-              accesskey: "pluginActivateNow.accesskey",
-              action: "_singleActivateNow"
-            };
-            button2 = {
-              label: "pluginActivateAlways.label",
-              accesskey: "pluginActivateAlways.accesskey",
-              action: "_singleActivateAlways"
-            };
-            switch (action.blocklistState) {
-            case Ci.nsIBlocklistService.STATE_NOT_BLOCKED:
-              label = "pluginActivate2.message";
-              linkLabel = "pluginActivate.learnMore";
-              button2.default = true;
-              break;
-
-            case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE:
-              label = "pluginActivateOutdated.message";
-              linkLabel = "pluginActivate.updateLabel";
-              button1.default = true;
-              break;
-
-            case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE:
-              label = "pluginActivateVulnerable.message";
-              linkLabel = "pluginActivate.riskLabel"
-              button1.default = true;
-              break;
-
-            default:
-              Cu.reportError(Error("Unexpected blocklist state"));
-            }
-
-            // TODO: temporary compromise, remove this once bug 892487 is fixed
-            if (isWindowPrivate) {
-              button1.default = true;
-              this._secondaryButton.hidden = true;
-            }
-          }
-          this._setupDescription(label, action.pluginName, prePath);
-          this._setupLink(linkLabel, action.detailsLink);
-
-          this._primaryButton.label = gNavigatorBundle.getString(button1.label);
-          this._primaryButton.accessKey = gNavigatorBundle.getString(button1.accesskey);
-          this._primaryButton.setAttribute("action", button1.action);
-
-          this._secondaryButton.label = gNavigatorBundle.getString(button2.label);
-          this._secondaryButton.accessKey = gNavigatorBundle.getString(button2.accesskey);
-          this._secondaryButton.setAttribute("action", button2.action);
-          if (button1.default) {
-            this._primaryButton.setAttribute("default", "true");
-          } else if (button2.default) {
-            this._secondaryButton.setAttribute("default", "true");
-          }
-
-          if (this._primaryButton.hidden) {
-            this._secondaryButton.setAttribute("alone", "true");
-          } else if (this._secondaryButton.hidden) {
-            this._primaryButton.setAttribute("alone", "true");
-          }
-        ]]></body>
-      </method>
-      <method name="_setupDescription">
-        <parameter name="baseString" />
-        <parameter name="pluginName" /> <!-- null for the multiple-plugin case -->
-        <parameter name="prePath" />
-        <body><![CDATA[
-          var span = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description");
-          while (span.lastChild) {
-            span.removeChild(span.lastChild);
-          }
-
-          var args = ["__prepath__", this._brandShortName];
-          if (pluginName) {
-            args.unshift(pluginName);
-          }
-          var bases = gNavigatorBundle.getFormattedString(baseString, args).
-            split("__prepath__", 2);
-
-          span.appendChild(document.createTextNode(bases[0]));
-          var prePathSpan = document.createElementNS("http://www.w3.org/1999/xhtml", "em");
-          prePathSpan.appendChild(document.createTextNode(prePath));
-          span.appendChild(prePathSpan);
-          span.appendChild(document.createTextNode(bases[1] + " "));
-        ]]></body>
-      </method>
-      <method name="_setupLink">
-        <parameter name="linkString"/>
-        <parameter name="linkUrl" />
-        <body><![CDATA[
-          var link = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-link");
-          if (!linkString || !linkUrl) {
-            link.hidden = true;
-            return;
-          }
-
-          link.hidden = false;
-          link.textContent = gNavigatorBundle.getString(linkString);
-          link.href = linkUrl;
-        ]]></body>
-      </method>
-      <method name="_onButton">
-        <parameter name="aButton" />
-        <body><![CDATA[
-          let methodName = aButton.getAttribute("action");
-          this[methodName]();
-        ]]></body>
-      </method>
-      <method name="_singleActivateNow">
-        <body><![CDATA[
-          gPluginHandler._updatePluginPermission(this.notification,
-            this._items[0].action,
-            "allownow");
-          this._cancel();
-        ]]></body>
-      </method>
-      <method name="_singleBlock">
-        <body><![CDATA[
-          gPluginHandler._updatePluginPermission(this.notification,
-            this._items[0].action,
-            "block");
-            this._cancel();
-        ]]></body>
-      </method>
-      <method name="_singleActivateAlways">
-        <body><![CDATA[
-          gPluginHandler._updatePluginPermission(this.notification,
-            this._items[0].action,
-            "allowalways");
-          this._cancel();
-        ]]></body>
-      </method>
-      <method name="_singleContinue">
-        <body><![CDATA[
-          gPluginHandler._updatePluginPermission(this.notification,
-            this._items[0].action,
-            "continue");
-          this._cancel();
-        ]]></body>
-      </method>
-      <method name="_multiAccept">
-        <body><![CDATA[
-          for (let item of this._items) {
-            let action = item.action;
-            if (action.pluginTag.enabledState == Ci.nsIPluginTag.STATE_DISABLED ||
-                action.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) {
-              continue;
-            }
-            gPluginHandler._updatePluginPermission(this.notification,
-              item.action, item.value);
-          }
-          this._cancel();
-        ]]></body>
-      </method>
-      <method name="_cancel">
-        <body><![CDATA[
-          PopupNotifications._dismiss();
-        ]]></body>
-      </method>
-      <method name="_accept">
-        <parameter name="aEvent" />
-        <body><![CDATA[
-          if (aEvent.defaultPrevented)
-            return;
-          aEvent.preventDefault();
-          if (this._primaryButton.getAttribute("default") == "true") {
-            this._primaryButton.click();
-          } else if (this._secondaryButton.getAttribute("default") == "true") {
-            this._secondaryButton.click();
-          }
-        ]]></body>
-      </method>
-    </implementation>
-    <handlers>
-      <!-- The _accept method checks for .defaultPrevented so that if focus is in a button,
-           enter activates the button and not this default action -->
-      <handler event="keypress" keycode="VK_RETURN" group="system" action="this._accept(event);"/>
-    </handlers>
-  </binding>
 </bindings>
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -1532,24 +1532,24 @@ CustomizeMode.prototype = {
       this._updateEmptyPaletteNotice();
     }
     CustomizableUI.dispatchToolboxEvent("customizationchange");
   },
 
   _updateEmptyPaletteNotice() {
     let paletteItems = this.visiblePalette.getElementsByTagName("toolbarpaletteitem");
     this.paletteEmptyNotice.hidden = !!paletteItems.length;
-    let readyPlayerOne = this.document.getElementById("ready-player-one");
+    let whimsyButton = this.document.getElementById("whimsy-button");
 
     if (paletteItems.length == 1 &&
         paletteItems[0].id.includes("wrapper-customizableui-special-spring")) {
-      readyPlayerOne.hidden = false;
+      whimsyButton.hidden = false;
     } else {
       this.togglePong(false);
-      readyPlayerOne.hidden = true;
+      whimsyButton.hidden = true;
     }
   },
 
   _updateResetButton() {
     let btn = this.document.getElementById("customization-reset-button");
     btn.disabled = CustomizableUI.inDefaultState;
   },
 
@@ -2528,18 +2528,18 @@ CustomizeMode.prototype = {
     // Ensure we move the button (back) after the user leaves customize mode.
     event.view.gCustomizeMode._moveDownloadsButtonToNavBar = checkbox.checked;
   },
 
   togglePong(enabled) {
     // It's possible we're toggling for a reason other than hitting
     // the button (we might be exiting, for example), so make sure that
     // the state and checkbox are in sync.
-    let readyPlayerOne = this.document.getElementById("ready-player-one");
-    readyPlayerOne.checked = enabled;
+    let whimsyButton = this.document.getElementById("whimsy-button");
+    whimsyButton.checked = enabled;
 
     if (enabled) {
       this.visiblePalette.setAttribute("whimsypong", "true");
       this.pongArena.hidden = false;
       if (!this.uninitWhimsy) {
         this.uninitWhimsy = this.whimsypong();
       }
     } else {
@@ -2668,16 +2668,17 @@ CustomizeMode.prototype = {
       if (rAFHandle) {
         window.cancelAnimationFrame(rAFHandle);
       }
       let arena = elements.arena;
       while (arena.firstChild) {
         arena.firstChild.remove();
       }
       arena.removeAttribute("score");
+      arena.removeAttribute("lives");
       arena.style.removeProperty("background-image");
       arena.style.removeProperty("background-position");
       arena.style.removeProperty("background-repeat");
       arena.style.removeProperty("background-size");
       elements = null;
       document = null;
       quit = true;
     }
@@ -2725,16 +2726,17 @@ CustomizeMode.prototype = {
     let window = this.window;
     rAFHandle = window.requestAnimationFrame(function animate() {
       update();
       draw();
       if (quit) {
         elements.score.textContent = score;
         elements.lives && elements.lives.setAttribute("lives", lives);
         elements.arena.setAttribute("score", score);
+        elements.arena.setAttribute("lives", "0");
       } else {
         rAFHandle = window.requestAnimationFrame(animate);
       }
     });
 
     return uninit;
   },
 };
--- a/browser/components/customizableui/content/customizeMode.inc.xul
+++ b/browser/components/customizableui/content/customizeMode.inc.xul
@@ -123,17 +123,17 @@
         <checkbox id="customization-uidensity-autotouchmode-checkbox"
                   hidden="true"
                   label="&customizeMode.uidensity.autoTouchMode.checkbox.label;"
                   oncommand="gCustomizeMode.updateAutoTouchMode(this.checked)"/>
 #endif
       </panel>
     </button>
 
-    <button id="ready-player-one"
+    <button id="whimsy-button"
             type="checkbox"
             class="customizationmode-button"
             oncommand="gCustomizeMode.togglePong(this.checked);"
             hidden="true"/>
 
     <spacer id="customization-footer-spacer"/>
     <button id="customization-undo-reset-button"
             class="customizationmode-button"
--- a/browser/components/extensions/ext-browser.js
+++ b/browser/components/extensions/ext-browser.js
@@ -46,17 +46,17 @@ const getSender = (extension, target, se
     }
   }
 };
 
 // Used by Extension.jsm
 global.tabGetSender = getSender;
 
 /* eslint-disable mozilla/balanced-listeners */
-extensions.on("uninstall", (msg, extension) => {
+extensions.on("uninstalling", (msg, extension) => {
   if (extension.uninstallURL) {
     let browser = windowTracker.topWindow.gBrowser;
     browser.addTab(extension.uninstallURL, {relatedToCurrent: true});
   }
 });
 
 extensions.on("page-shutdown", (type, context) => {
   if (context.viewType == "tab") {
--- a/browser/components/extensions/test/browser/browser_ext_webRequest.js
+++ b/browser/components/extensions/test/browser/browser_ext_webRequest.js
@@ -4,16 +4,18 @@
 
 /* import-globals-from ../../../../../toolkit/components/extensions/test/mochitest/head_webrequest.js */
 Services.scriptloader.loadSubScript(new URL("head_webrequest.js", gTestPath).href,
                                     this);
 
 Cu.import("resource://testing-common/HiddenFrame.jsm", this);
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
+SimpleTest.requestCompleteLog();
+
 function createHiddenBrowser(url) {
   let frame = new HiddenFrame();
   return new Promise(resolve =>
     frame.get().then(subframe => {
       let doc = subframe.document;
       let browser = doc.createElementNS(XUL_NS, "browser");
       browser.setAttribute("type", "content");
       browser.setAttribute("disableglobalhistory", "true");
@@ -49,18 +51,27 @@ let headers = {
       "content-type": "text/html; charset=utf-8",
     },
     remove: [
       "connection",
     ],
   },
 };
 
+let urls = ["http://mochi.test/browser/*"];
+let events = {
+  "onBeforeRequest":     [{urls}, ["blocking"]],
+  "onBeforeSendHeaders": [{urls}, ["blocking", "requestHeaders"]],
+  "onSendHeaders":       [{urls}, ["requestHeaders"]],
+  "onHeadersReceived":   [{urls}, ["blocking", "responseHeaders"]],
+  "onCompleted":         [{urls}, ["responseHeaders"]],
+};
+
 add_task(async function setup() {
-  extension = makeExtension();
+  extension = makeExtension(events);
   await extension.startup();
 });
 
 add_task(async function test_newWindow() {
   let expect = {
     "file_dummy.html": {
       type: "main_frame",
       headers,
@@ -70,50 +81,54 @@ add_task(async function test_newWindow()
   // the tests in this file, so all tests ignore it.  When running with
   // other tests in this directory, favicon gets loaded at some point before
   // we run, and we never see the request, thus it cannot be handled as part
   // of expect above.
   extension.sendMessage("set-expected", {expect, ignore: ["favicon.ico"]});
   await extension.awaitMessage("continue");
 
   let openedWindow = await BrowserTestUtils.openNewBrowserWindow();
-  await BrowserTestUtils.openNewForegroundTab(openedWindow.gBrowser, dummy + "?newWindow");
+  await BrowserTestUtils.openNewForegroundTab(openedWindow.gBrowser, `${dummy}?newWindow=${Math.random()}`);
 
   await extension.awaitMessage("done");
   await BrowserTestUtils.closeWindow(openedWindow);
 });
 
 add_task(async function test_newTab() {
   // again, in this window
   let expect = {
     "file_dummy.html": {
       type: "main_frame",
       headers,
     },
   };
   extension.sendMessage("set-expected", {expect, ignore: ["favicon.ico"]});
   await extension.awaitMessage("continue");
-  let tab = await BrowserTestUtils.openNewForegroundTab(window.gBrowser, dummy + "?newTab");
+  let tab = await BrowserTestUtils.openNewForegroundTab(window.gBrowser, `${dummy}?newTab=${Math.random()}`);
 
   await extension.awaitMessage("done");
   await BrowserTestUtils.removeTab(tab);
 });
 
 add_task(async function test_subframe() {
   let expect = {
     "file_dummy.html": {
       type: "main_frame",
       headers,
     },
   };
   // test a content subframe attached to hidden window
   extension.sendMessage("set-expected", {expect, ignore: ["favicon.ico"]});
+  info("*** waiting to continue");
   await extension.awaitMessage("continue");
-  let frameInfo = await createHiddenBrowser(dummy + "?subframe");
+  info("*** creating hidden browser");
+  let frameInfo = await createHiddenBrowser(`${dummy}?subframe=${Math.random()}`);
+  info("*** waiting for finish");
   await extension.awaitMessage("done");
+  info("*** destroying hidden browser");
   // cleanup
   frameInfo.browser.remove();
   frameInfo.frame.destroy();
 });
 
 add_task(async function teardown() {
   await extension.unload();
 });
--- a/browser/extensions/formautofill/test/unit/head.js
+++ b/browser/extensions/formautofill/test/unit/head.js
@@ -10,16 +10,17 @@
 
 var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/ObjectUtils.jsm");
 Cu.import("resource://gre/modules/FormLikeFactory.jsm");
+Cu.import("resource://testing-common/FileTestUtils.jsm");
 Cu.import("resource://testing-common/MockDocument.jsm");
 Cu.import("resource://testing-common/TestUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadPaths",
                                   "resource://gre/modules/DownloadPaths.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
 
@@ -46,53 +47,20 @@ let bootstrapURI = Services.io.newFileUR
 if (!extensionDir.exists()) {
   extensionDir = extensionDir.parent;
   extensionDir.append(EXTENSION_ID + ".xpi");
   let jarURI = Services.io.newFileURI(extensionDir);
   bootstrapURI = "jar:" + jarURI.spec + "!/bootstrap.js";
 }
 Components.manager.addBootstrappedManifestLocation(extensionDir);
 
-// While the previous test file should have deleted all the temporary files it
-// used, on Windows these might still be pending deletion on the physical file
-// system.  Thus, start from a new base number every time, to make a collision
-// with a file that is still pending deletion highly unlikely.
-let gFileCounter = Math.floor(Math.random() * 1000000);
-
-/**
- * Returns a reference to a temporary file, that is guaranteed not to exist, and
- * to have never been created before.
- *
- * @param {string} leafName
- *        Suggested leaf name for the file to be created.
- *
- * @returns {nsIFile} pointing to a non-existent file in a temporary directory.
- *
- * @note It is not enough to delete the file if it exists, or to delete the file
- *       after calling nsIFile.createUnique, because on Windows the delete
- *       operation in the file system may still be pending, preventing a new
- *       file with the same name to be created.
- */
+// Returns a reference to a temporary file that is guaranteed not to exist and
+// is cleaned up later. See FileTestUtils.getTempFile for details.
 function getTempFile(leafName) {
-  // Prepend a serial number to the extension in the suggested leaf name.
-  let [base, ext] = DownloadPaths.splitBaseNameAndExtension(leafName);
-  let finalLeafName = base + "-" + gFileCounter + ext;
-  gFileCounter++;
-
-  // Get a file reference under the temporary directory for this test file.
-  let file = FileUtils.getFile("TmpD", [finalLeafName]);
-  do_check_false(file.exists());
-
-  do_register_cleanup(function() {
-    if (file.exists()) {
-      file.remove(false);
-    }
-  });
-
-  return file;
+  return FileTestUtils.getTempFile(leafName);
 }
 
 async function initProfileStorage(fileName, records, collectionName = "addresses") {
   let {ProfileStorage} = Cu.import("resource://formautofill/ProfileStorage.jsm", {});
   let path = getTempFile(fileName).path;
   let profileStorage = new ProfileStorage(path);
   await profileStorage.initialize();
 
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,5 +1,5 @@
 This is the PDF.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 1.10.88
+Current extension version is: 2.0.87
 
-Taken from upstream commit: c62a1938
+Taken from upstream commit: b46443f0
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -1451,17 +1451,17 @@ exports.unreachable = unreachable;
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.SimpleXMLParser = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.getDefaultSetting = exports.LinkTarget = exports.getFilenameFromUrl = exports.isValidUrl = exports.isExternalLinkTargetSet = exports.addLinkAttributes = exports.RenderingCancelledException = exports.CustomStyle = undefined;
+exports.SimpleXMLParser = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.getDefaultSetting = exports.LinkTarget = exports.getFilenameFromUrl = exports.isExternalLinkTargetSet = exports.addLinkAttributes = exports.RenderingCancelledException = exports.CustomStyle = undefined;
 
 var _util = __w_pdfjs_require__(0);
 
 var _global_scope = __w_pdfjs_require__(2);
 
 var _global_scope2 = _interopRequireDefault(_global_scope);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -1784,44 +1784,36 @@ function getDefaultSetting(id) {
       }
       (0, _util.warn)('PDFJS.externalLinkTarget is invalid: ' + globalSettings.externalLinkTarget);
       globalSettings.externalLinkTarget = LinkTarget.NONE;
       return LinkTarget.NONE;
     case 'externalLinkRel':
       return globalSettings ? globalSettings.externalLinkRel : DEFAULT_LINK_REL;
     case 'enableStats':
       return !!(globalSettings && globalSettings.enableStats);
-    case 'pdfjsNext':
-      return !!(globalSettings && globalSettings.pdfjsNext);
     default:
       throw new Error('Unknown default setting: ' + id);
   }
 }
 function isExternalLinkTargetSet() {
   var externalLinkTarget = getDefaultSetting('externalLinkTarget');
   switch (externalLinkTarget) {
     case LinkTarget.NONE:
       return false;
     case LinkTarget.SELF:
     case LinkTarget.BLANK:
     case LinkTarget.PARENT:
     case LinkTarget.TOP:
       return true;
   }
 }
-function isValidUrl(url, allowRelative) {
-  (0, _util.deprecated)('isValidUrl(), please use createValidAbsoluteUrl() instead.');
-  var baseUrl = allowRelative ? 'http://example.com' : null;
-  return (0, _util.createValidAbsoluteUrl)(url, baseUrl) !== null;
-}
 exports.CustomStyle = CustomStyle;
 exports.RenderingCancelledException = RenderingCancelledException;
 exports.addLinkAttributes = addLinkAttributes;
 exports.isExternalLinkTargetSet = isExternalLinkTargetSet;
-exports.isValidUrl = isValidUrl;
 exports.getFilenameFromUrl = getFilenameFromUrl;
 exports.LinkTarget = LinkTarget;
 exports.getDefaultSetting = getDefaultSetting;
 exports.DEFAULT_LINK_REL = DEFAULT_LINK_REL;
 exports.DOMCanvasFactory = DOMCanvasFactory;
 exports.DOMCMapReaderFactory = DOMCMapReaderFactory;
 exports.DOMSVGFactory = DOMSVGFactory;
 exports.SimpleXMLParser = SimpleXMLParser;
@@ -1840,17 +1832,17 @@ module.exports = typeof window !== 'unde
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.build = exports.version = exports._UnsupportedManager = exports.setPDFNetworkStreamClass = exports.PDFPageProxy = exports.PDFDocumentProxy = exports.PDFWorker = exports.PDFDataRangeTransport = exports.LoopbackPort = exports.getDocument = undefined;
+exports.build = exports.version = exports.setPDFNetworkStreamClass = exports.PDFPageProxy = exports.PDFDocumentProxy = exports.PDFWorker = exports.PDFDataRangeTransport = exports.LoopbackPort = exports.getDocument = undefined;
 
 var _util = __w_pdfjs_require__(0);
 
 var _dom_utils = __w_pdfjs_require__(1);
 
 var _font_loader = __w_pdfjs_require__(14);
 
 var _canvas = __w_pdfjs_require__(15);
@@ -1872,35 +1864,18 @@ var isPostMessageTransfersDisabled = fal
 var pdfjsFilePath = null;
 var fakeWorkerFilesLoader = null;
 var useRequireEnsure = false;
 ;
 var PDFNetworkStream;
 function setPDFNetworkStreamClass(cls) {
   PDFNetworkStream = cls;
 }
-function getDocument(src, pdfDataRangeTransport, passwordCallback, progressCallback) {
+function getDocument(src) {
   var task = new PDFDocumentLoadingTask();
-  if (arguments.length > 1) {
-    (0, _util.deprecated)('getDocument is called with pdfDataRangeTransport, ' + 'passwordCallback or progressCallback argument');
-  }
-  if (pdfDataRangeTransport) {
-    if (!(pdfDataRangeTransport instanceof PDFDataRangeTransport)) {
-      pdfDataRangeTransport = Object.create(pdfDataRangeTransport);
-      pdfDataRangeTransport.length = src.length;
-      pdfDataRangeTransport.initialData = src.initialData;
-      if (!pdfDataRangeTransport.abort) {
-        pdfDataRangeTransport.abort = function () {};
-      }
-    }
-    src = Object.create(src);
-    src.range = pdfDataRangeTransport;
-  }
-  task.onPassword = passwordCallback || null;
-  task.onProgress = progressCallback || null;
   var source;
   if (typeof src === 'string') {
     source = { url: src };
   } else if ((0, _util.isArrayBuffer)(src)) {
     source = { data: src };
   } else if (src instanceof PDFDataRangeTransport) {
     source = { range: src };
   } else {
@@ -1941,22 +1916,18 @@ function getDocument(src, pdfDataRangeTr
     } else if (key === 'CMapReaderFactory') {
       CMapReaderFactory = source[key];
       continue;
     }
     params[key] = source[key];
   }
   params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
   params.ignoreErrors = params.stopAtErrors !== true;
-  if (params.disableNativeImageDecoder !== undefined) {
-    (0, _util.deprecated)('parameter disableNativeImageDecoder, ' + 'use nativeImageDecoderSupport instead');
-  }
-  params.nativeImageDecoderSupport = params.nativeImageDecoderSupport || (params.disableNativeImageDecoder === true ? _util.NativeImageDecoding.NONE : _util.NativeImageDecoding.DECODE);
-  if (params.nativeImageDecoderSupport !== _util.NativeImageDecoding.DECODE && params.nativeImageDecoderSupport !== _util.NativeImageDecoding.NONE && params.nativeImageDecoderSupport !== _util.NativeImageDecoding.DISPLAY) {
-    (0, _util.warn)('Invalid parameter nativeImageDecoderSupport: ' + 'need a state of enum {NativeImageDecoding}');
+  const nativeImageDecoderValues = Object.values(_util.NativeImageDecoding);
+  if (params.nativeImageDecoderSupport === undefined || !nativeImageDecoderValues.includes(params.nativeImageDecoderSupport)) {
     params.nativeImageDecoderSupport = _util.NativeImageDecoding.DECODE;
   }
   if (!worker) {
     var workerPort = (0, _dom_utils.getDefaultSetting)('workerPort');
     worker = workerPort ? PDFWorker.fromPort(workerPort) : new PDFWorker();
     task._worker = worker;
   }
   var docId = task.docId;
@@ -1985,17 +1956,17 @@ function getDocument(src, pdfDataRangeTr
     });
   }).catch(task._capability.reject);
   return task;
 }
 function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
   if (worker.destroyed) {
     return Promise.reject(new Error('Worker was destroyed'));
   }
-  let apiVersion = '1.10.88';
+  let apiVersion = '2.0.87';
   source.disableAutoFetch = (0, _dom_utils.getDefaultSetting)('disableAutoFetch');
   source.disableStream = (0, _dom_utils.getDefaultSetting)('disableStream');
   source.chunkedViewerLoading = !!pdfDataRangeTransport;
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
   }
   return worker.messageHandler.sendWithPromise('GetDocRequest', {
@@ -2137,17 +2108,17 @@ var PDFDocumentProxy = function PDFDocum
       return this.transport.getPageLabels();
     },
     getPageMode() {
       return this.transport.getPageMode();
     },
     getAttachments: function PDFDocumentProxy_getAttachments() {
       return this.transport.getAttachments();
     },
-    getJavaScript: function PDFDocumentProxy_getJavaScript() {
+    getJavaScript() {
       return this.transport.getJavaScript();
     },
     getOutline: function PDFDocumentProxy_getOutline() {
       return this.transport.getOutline();
     },
     getMetadata: function PDFDocumentProxy_getMetadata() {
       return this.transport.getMetadata();
     },
@@ -2257,20 +2228,16 @@ var PDFPageProxy = function PDFPageProxy
       };
       var internalRenderTask = new InternalRenderTask(complete, params, this.objs, this.commonObjs, intentState.operatorList, this.pageNumber, canvasFactory);
       internalRenderTask.useRequestAnimationFrame = renderingIntent !== 'print';
       if (!intentState.renderTasks) {
         intentState.renderTasks = [];
       }
       intentState.renderTasks.push(internalRenderTask);
       var renderTask = internalRenderTask.task;
-      if (params.continueCallback) {
-        (0, _util.deprecated)('render is used with continueCallback parameter');
-        renderTask.onContinue = params.continueCallback;
-      }
       intentState.displayReadyCapability.promise.then(transparency => {
         if (this.pendingCleanup) {
           complete();
           return;
         }
         stats.time('Rendering');
         internalRenderTask.initializeGraphics(transparency);
         internalRenderTask.operatorListChanged();
@@ -2363,20 +2330,16 @@ var PDFPageProxy = function PDFPageProxy
           renderTask.cancel();
         });
       }, this);
       this.objs.clear();
       this.annotationsPromise = null;
       this.pendingCleanup = false;
       return Promise.all(waitOn);
     },
-    destroy() {
-      (0, _util.deprecated)('page destroy method, use cleanup() instead');
-      this.cleanup();
-    },
     cleanup: function PDFPageProxy_cleanup() {
       this.pendingCleanup = true;
       this._tryCleanup();
     },
     _tryCleanup: function PDFPageProxy_tryCleanup() {
       if (!this.pendingCleanup || Object.keys(this.intentStates).some(function (intent) {
         var intentState = this.intentStates[intent];
         return intentState.renderTasks.length !== 0 || intentState.receivingOperatorList;
@@ -2954,26 +2917,24 @@ var WorkerTransport = function WorkerTra
         }
         if (intentState.operatorList) {
           intentState.operatorList.lastChunk = true;
           for (var i = 0; i < intentState.renderTasks.length; i++) {
             intentState.renderTasks[i].operatorListChanged();
           }
         }
       }, this);
-      messageHandler.on('UnsupportedFeature', function transportUnsupportedFeature(data) {
+      messageHandler.on('UnsupportedFeature', function (data) {
         if (this.destroyed) {
           return;
         }
-        var featureId = data.featureId;
-        var loadingTask = this.loadingTask;
+        let loadingTask = this.loadingTask;
         if (loadingTask.onUnsupportedFeature) {
-          loadingTask.onUnsupportedFeature(featureId);
-        }
-        _UnsupportedManager.notify(featureId);
+          loadingTask.onUnsupportedFeature(data.featureId);
+        }
       }, this);
       messageHandler.on('JpegDecode', function (data) {
         if (this.destroyed) {
           return Promise.reject(new Error('Worker was destroyed'));
         }
         if (typeof document === 'undefined') {
           return Promise.reject(new Error('"document" is not defined.'));
         }
@@ -3290,43 +3251,28 @@ var InternalRenderTask = function Intern
           }
           this.callback();
         }
       }
     }
   };
   return InternalRenderTask;
 }();
-var _UnsupportedManager = function UnsupportedManagerClosure() {
-  var listeners = [];
-  return {
-    listen(cb) {
-      (0, _util.deprecated)('Global UnsupportedManager.listen is used: ' + ' use PDFDocumentLoadingTask.onUnsupportedFeature instead');
-      listeners.push(cb);
-    },
-    notify(featureId) {
-      for (var i = 0, ii = listeners.length; i < ii; i++) {
-        listeners[i](featureId);
-      }
-    }
-  };
-}();
 var version, build;
 {
-  exports.version = version = '1.10.88';
-  exports.build = build = 'c62a1938';
+  exports.version = version = '2.0.87';
+  exports.build = build = 'b46443f0';
 }
 exports.getDocument = getDocument;
 exports.LoopbackPort = LoopbackPort;
 exports.PDFDataRangeTransport = PDFDataRangeTransport;
 exports.PDFWorker = PDFWorker;
 exports.PDFDocumentProxy = PDFDocumentProxy;
 exports.PDFPageProxy = PDFPageProxy;
 exports.setPDFNetworkStreamClass = setPDFNetworkStreamClass;
-exports._UnsupportedManager = _UnsupportedManager;
 exports.version = version;
 exports.build = build;
 
 /***/ }),
 /* 4 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
@@ -3765,20 +3711,16 @@ class Metadata {
     return this._metadata[name] || null;
   }
   getAll() {
     return this._metadata;
   }
   has(name) {
     return typeof this._metadata[name] !== 'undefined';
   }
-  get metadata() {
-    (0, _util.deprecated)('`metadata` getter; use `getAll()` instead.');
-    return this.getAll();
-  }
 }
 exports.Metadata = Metadata;
 
 /***/ }),
 /* 6 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
@@ -5046,18 +4988,18 @@ exports.SVGGraphics = SVGGraphics;
 
 /***/ }),
 /* 9 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '1.10.88';
-var pdfjsBuild = 'c62a1938';
+var pdfjsVersion = '2.0.87';
+var pdfjsBuild = 'b46443f0';
 var pdfjsSharedUtil = __w_pdfjs_require__(0);
 var pdfjsDisplayGlobal = __w_pdfjs_require__(13);
 var pdfjsDisplayAPI = __w_pdfjs_require__(3);
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(7);
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(6);
 var pdfjsDisplayDOMUtils = __w_pdfjs_require__(1);
 var pdfjsDisplaySVG = __w_pdfjs_require__(8);
 ;
@@ -5075,17 +5017,16 @@ exports.createPromiseCapability = pdfjsS
 exports.PasswordResponses = pdfjsSharedUtil.PasswordResponses;
 exports.InvalidPDFException = pdfjsSharedUtil.InvalidPDFException;
 exports.MissingPDFException = pdfjsSharedUtil.MissingPDFException;
 exports.SVGGraphics = pdfjsDisplaySVG.SVGGraphics;
 exports.NativeImageDecoding = pdfjsSharedUtil.NativeImageDecoding;
 exports.UnexpectedResponseException = pdfjsSharedUtil.UnexpectedResponseException;
 exports.OPS = pdfjsSharedUtil.OPS;
 exports.UNSUPPORTED_FEATURES = pdfjsSharedUtil.UNSUPPORTED_FEATURES;
-exports.isValidUrl = pdfjsDisplayDOMUtils.isValidUrl;
 exports.createValidAbsoluteUrl = pdfjsSharedUtil.createValidAbsoluteUrl;
 exports.createObjectURL = pdfjsSharedUtil.createObjectURL;
 exports.removeNullCharacters = pdfjsSharedUtil.removeNullCharacters;
 exports.shadow = pdfjsSharedUtil.shadow;
 exports.createBlob = pdfjsSharedUtil.createBlob;
 exports.RenderingCancelledException = pdfjsDisplayDOMUtils.RenderingCancelledException;
 exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl;
 exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes;
@@ -8147,22 +8088,22 @@ if (isReadableStreamSupported) {
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFJS = exports.globalScope = undefined;
 
-var _api = __w_pdfjs_require__(3);
-
 var _dom_utils = __w_pdfjs_require__(1);
 
 var _util = __w_pdfjs_require__(0);
 
+var _api = __w_pdfjs_require__(3);
+
 var _annotation_layer = __w_pdfjs_require__(6);
 
 var _global_scope = __w_pdfjs_require__(2);
 
 var _global_scope2 = _interopRequireDefault(_global_scope);
 
 var _metadata = __w_pdfjs_require__(5);
 
@@ -8172,18 +8113,18 @@ var _svg = __w_pdfjs_require__(8);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 if (!_global_scope2.default.PDFJS) {
   _global_scope2.default.PDFJS = {};
 }
 var PDFJS = _global_scope2.default.PDFJS;
 {
-  PDFJS.version = '1.10.88';
-  PDFJS.build = 'c62a1938';
+  PDFJS.version = '2.0.87';
+  PDFJS.build = 'b46443f0';
 }
 PDFJS.pdfBug = false;
 if (PDFJS.verbosity !== undefined) {
   (0, _util.setVerbosityLevel)(PDFJS.verbosity);
 }
 delete PDFJS.verbosity;
 Object.defineProperty(PDFJS, 'verbosity', {
   get() {
@@ -8233,33 +8174,30 @@ PDFJS.disableStream = PDFJS.disableStrea
 PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ? false : PDFJS.disableAutoFetch;
 PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
 PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ? true : PDFJS.postMessageTransfers;
 PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ? false : PDFJS.disableCreateObjectURL;
 PDFJS.disableWebGL = PDFJS.disableWebGL === undefined ? true : PDFJS.disableWebGL;
 PDFJS.externalLinkTarget = PDFJS.externalLinkTarget === undefined ? _dom_utils.LinkTarget.NONE : PDFJS.externalLinkTarget;
 PDFJS.externalLinkRel = PDFJS.externalLinkRel === undefined ? _dom_utils.DEFAULT_LINK_REL : PDFJS.externalLinkRel;
 PDFJS.isEvalSupported = PDFJS.isEvalSupported === undefined ? true : PDFJS.isEvalSupported;
-PDFJS.pdfjsNext = PDFJS.pdfjsNext === undefined ? false : PDFJS.pdfjsNext;
-;
 PDFJS.getDocument = _api.getDocument;
 PDFJS.LoopbackPort = _api.LoopbackPort;
 PDFJS.PDFDataRangeTransport = _api.PDFDataRangeTransport;
 PDFJS.PDFWorker = _api.PDFWorker;
 PDFJS.hasCanvasTypedArrays = true;
 PDFJS.CustomStyle = _dom_utils.CustomStyle;
 PDFJS.LinkTarget = _dom_utils.LinkTarget;
 PDFJS.addLinkAttributes = _dom_utils.addLinkAttributes;
 PDFJS.getFilenameFromUrl = _dom_utils.getFilenameFromUrl;
 PDFJS.isExternalLinkTargetSet = _dom_utils.isExternalLinkTargetSet;
 PDFJS.AnnotationLayer = _annotation_layer.AnnotationLayer;
 PDFJS.renderTextLayer = _text_layer.renderTextLayer;
 PDFJS.Metadata = _metadata.Metadata;
 PDFJS.SVGGraphics = _svg.SVGGraphics;
-PDFJS.UnsupportedManager = _api._UnsupportedManager;
 exports.globalScope = _global_scope2.default;
 exports.PDFJS = PDFJS;
 
 /***/ }),
 /* 14 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -10092,28 +10092,31 @@ var Catalog = function CatalogClosure() 
           attachments[(0, _util.stringToPDFString)(name)] = fs.serializable;
         }
       }
       return (0, _util.shadow)(this, 'attachments', attachments);
     },
     get javaScript() {
       var xref = this.xref;
       var obj = this.catDict.get('Names');
-      var javaScript = [];
+      let javaScript = null;
       function appendIfJavaScriptDict(jsDict) {
         var type = jsDict.get('S');
         if (!(0, _primitives.isName)(type, 'JavaScript')) {
           return;
         }
         var js = jsDict.get('JS');
         if ((0, _primitives.isStream)(js)) {
           js = (0, _util.bytesToString)(js.getBytes());
         } else if (!(0, _util.isString)(js)) {
           return;
         }
+        if (!javaScript) {
+          javaScript = [];
+        }
         javaScript.push((0, _util.stringToPDFString)(js));
       }
       if (obj && obj.has('JavaScript')) {
         var nameTree = new NameTree(obj.getRaw('JavaScript'), xref);
         var names = nameTree.getAll();
         for (var name in names) {
           var jsDict = names[name];
           if ((0, _primitives.isDict)(jsDict)) {
@@ -10122,16 +10125,19 @@ var Catalog = function CatalogClosure() 
         }
       }
       var openactionDict = this.catDict.get('OpenAction');
       if ((0, _primitives.isDict)(openactionDict, 'Action')) {
         var actionType = openactionDict.get('S');
         if ((0, _primitives.isName)(actionType, 'Named')) {
           var action = openactionDict.get('N');
           if ((0, _primitives.isName)(action, 'Print')) {
+            if (!javaScript) {
+              javaScript = [];
+            }
             javaScript.push('print({});');
           }
         } else {
           appendIfJavaScriptDict(openactionDict);
         }
       }
       return (0, _util.shadow)(this, 'javaScript', javaScript);
     },
@@ -20268,16 +20274,18 @@ var getSpecialPUASymbols = getLookupTabl
  t[63735] = 0x239F;
  t[63736] = 0x23A0;
 });
 function mapSpecialUnicodeValues(code) {
  if (code >= 0xFFF0 && code <= 0xFFFF) {
   return 0;
  } else if (code >= 0xF600 && code <= 0xF8FF) {
   return getSpecialPUASymbols()[code] || code;
+ } else if (code === 0x00AD) {
+  return 0x002D;
  }
  return code;
 }
 function getUnicodeForGlyph(name, glyphsUnicodeMap) {
  var unicode = glyphsUnicodeMap[name];
  if (unicode !== undefined) {
   return unicode;
  }
@@ -23270,18 +23278,18 @@ exports.PostScriptCompiler = PostScriptC
 
 /***/ }),
 /* 17 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '1.10.88';
-var pdfjsBuild = 'c62a1938';
+var pdfjsVersion = '2.0.87';
+var pdfjsBuild = 'b46443f0';
 var pdfjsCoreWorker = __w_pdfjs_require__(18);
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 18 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
@@ -23466,17 +23474,17 @@ var WorkerMessageHandler = {
     });
   },
   createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     let apiVersion = docParams.apiVersion;
-    let workerVersion = '1.10.88';
+    let workerVersion = '2.0.87';
     if (apiVersion !== null && apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
     var docId = docParams.docId;
     var docBaseUrl = docParams.docBaseUrl;
     var workerHandlerName = docParams.docId + '_worker';
     var handler = new _util.MessageHandler(workerHandlerName, docId, port);
     handler.postMessageTransfers = docParams.postMessageTransfers;
@@ -31584,16 +31592,20 @@ var Font = function FontClosure() {
     var ID = 1;
     return function Font_getFontID() {
       return String(ID++);
     };
   }();
   function int16(b0, b1) {
     return (b0 << 8) + b1;
   }
+  function writeSignedInt16(bytes, index, value) {
+    bytes[index + 1] = value;
+    bytes[index] = value >>> 8;
+  }
   function signedInt16(b0, b1) {
     var value = (b0 << 8) + b1;
     return value & 1 << 15 ? value - 0x10000 : value;
   }
   function int32(b0, b1, b2, b3) {
     return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
   }
   function string16(value) {
@@ -32233,18 +32245,20 @@ var Font = function FontClosure() {
         var glyphProfile = {
           length: 0,
           sizeOfInstructions: 0
         };
         if (sourceEnd - sourceStart <= 12) {
           return glyphProfile;
         }
         var glyf = source.subarray(sourceStart, sourceEnd);
-        var contoursCount = glyf[0] << 8 | glyf[1];
-        if (contoursCount & 0x8000) {
+        var contoursCount = signedInt16(glyf[0], glyf[1]);
+        if (contoursCount < 0) {
+          contoursCount = -1;
+          writeSignedInt16(glyf, 0, contoursCount);
           dest.set(glyf, destStart);
           glyphProfile.length = glyf.length;
           return glyphProfile;
         }
         var i,
             j = 10,
             flagsCount = 0;
         for (i = 0; i < contoursCount; i++) {
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -1498,17 +1498,17 @@ let PDFViewerApplication = {
       this.toolbar.setPagesCount(pdfDocument.numPages, true);
       this.toolbar.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel);
     });
     pagesPromise.then(() => {
       if (!this.supportsPrinting) {
         return;
       }
       pdfDocument.getJavaScript().then(javaScript => {
-        if (javaScript.length === 0) {
+        if (!javaScript) {
           return;
         }
         javaScript.some(js => {
           if (!js) {
             return false;
           }
           console.warn('Warning: JavaScript is not supported');
           this.fallback(_pdfjsLib.UNSUPPORTED_FEATURES.javaScript);
@@ -2732,25 +2732,18 @@ const CursorTool = {
 class PDFCursorTools {
   constructor({ container, eventBus, preferences }) {
     this.container = container;
     this.eventBus = eventBus;
     this.active = CursorTool.SELECT;
     this.activeBeforePresentationMode = null;
     this.handTool = new _grab_to_pan.GrabToPan({ element: this.container });
     this._addEventListeners();
-    Promise.all([preferences.get('cursorToolOnLoad'), preferences.get('enableHandToolOnLoad')]).then(([cursorToolPref, handToolPref]) => {
-      if (handToolPref === true) {
-        preferences.set('enableHandToolOnLoad', false);
-        if (cursorToolPref === CursorTool.SELECT) {
-          cursorToolPref = CursorTool.HAND;
-          preferences.set('cursorToolOnLoad', cursorToolPref).catch(() => {});
-        }
-      }
-      this.switchTool(cursorToolPref);
+    preferences.get('cursorToolOnLoad').then(value => {
+      this.switchTool(value);
     }).catch(() => {});
   }
   get activeTool() {
     return this.active;
   }
   switchTool(tool) {
     if (this.activeBeforePresentationMode !== null) {
       return;
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -340,16 +340,25 @@ pluginActivateNow.accesskey=N
 # plugin.
 pluginActivateAlways.label=Allow and Remember
 pluginActivateAlways.accesskey=R
 pluginBlockNow.label=Block Plugin
 pluginBlockNow.accesskey=B
 pluginContinue.label=Continue Allowing
 pluginContinue.accesskey=C
 
+# Flash activation doorhanger UI
+flashActivate.message=Do you want to allow Adobe Flash to run on this site? Only allow Flash on sites you trust.
+flashActivate.outdated.message=Do you want to allow an outdated version of Flash to run on this site? An outdated version can affect browser performance and security.
+flashActivate.remember=Remember this decision
+flashActivate.noAllow=Don’t Allow
+flashActivate.allow=Allow
+flashActivate.noAllow.accesskey=D
+flashActivate.allow.accesskey=A
+
 # in-page UI
 PluginClickToActivate=Activate %S.
 PluginVulnerableUpdatable=This plugin is vulnerable and should be updated.
 PluginVulnerableNoUpdate=This plugin has security vulnerabilities.
 
 # infobar UI
 pluginContinueBlocking.label=Continue Blocking
 pluginContinueBlocking.accesskey=B
--- a/browser/locales/search/list.json
+++ b/browser/locales/search/list.json
@@ -505,17 +505,17 @@
         "visibleDefaultEngines": [
           "google", "wikipedia-lt", "bing", "amazondotcom", "ddg", "twitter"
         ]
       }
     },
     "ltg": {
       "default": {
         "visibleDefaultEngines": [
-          "google", "yahoo", "dict-enlv", "ddg", "salidzinilv", "sslv", "wikipedia-lv"
+          "google", "yahoo", "dict-enlv", "ddg", "salidzinilv", "sslv", "wikipedia-ltg"
         ]
       }
     },
     "lv": {
       "default": {
         "visibleDefaultEngines": [
           "google", "yahoo", "dict-enlv", "ddg", "salidzinilv", "sslv", "wikipedia-lv"
         ]
new file mode 100644
--- /dev/null
+++ b/browser/locales/searchplugins/wikipedia-ltg.xml
@@ -0,0 +1,19 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Vikipedeja (ltg)</ShortName>
+<Description>Vikipēdija, breivuo eņciklopedeja</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">resource://search-plugins/images/wikipedia.ico</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ltg.wikipedia.org/w/api.php">
+  <Param name="action" value="opensearch"/>
+  <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ltg.wikipedia.org/wiki/Seviškuo:Search"
+     resultdomain="wikipedia.org" rel="searchform">
+  <Param name="search" value="{searchTerms}"/>
+  <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+</SearchPlugin>
--- a/browser/locales/searchplugins/wikipedia-lv.xml
+++ b/browser/locales/searchplugins/wikipedia-lv.xml
@@ -1,15 +1,15 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
 <ShortName>Vikipēdija</ShortName>
-<Description>Vikipēdija, brīvā encikopēdija</Description>
+<Description>Vikipēdija, brīvā enciklopēdija</Description>
 <InputEncoding>UTF-8</InputEncoding>
 <Image width="16" height="16">resource://search-plugins/images/wikipedia.ico</Image>
 <Url type="application/x-suggestions+json" method="GET" template="https://lv.wikipedia.org/w/api.php">
   <Param name="action" value="opensearch"/>
   <Param name="search" value="{searchTerms}"/>
 </Url>
 <Url type="text/html" method="GET" template="https://lv.wikipedia.org/wiki/Special:Search"
      resultdomain="wikipedia.org" rel="searchform">
--- a/browser/modules/PluginContent.jsm
+++ b/browser/modules/PluginContent.jsm
@@ -25,16 +25,20 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
 this.PluginContent = function(global) {
   this.init(global);
 };
 
 const FLASH_MIME_TYPE = "application/x-shockwave-flash";
 const REPLACEMENT_STYLE_SHEET = Services.io.newURI("chrome://pluginproblem/content/pluginReplaceBinding.css");
 
+const OVERLAY_DISPLAY_HIDDEN = 0;
+const OVERLAY_DISPLAY_VISIBLE = 1;
+const OVERLAY_DISPLAY_MINIMAL = 2;
+
 PluginContent.prototype = {
   init(global) {
     this.global = global;
     // Need to hold onto the content window or else it'll get destroyed
     this.content = this.global.content;
     // Cache of plugin actions for the current page.
     this.pluginData = new Map();
     // Cache of plugin crash information sent from the parent
@@ -279,46 +283,55 @@ PluginContent.prototype = {
              fallbackType: Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
              blocklistState,
            };
   },
 
   /**
    * Update the visibility of the plugin overlay.
    */
-  setVisibility(plugin, overlay, shouldShow) {
-    overlay.classList.toggle("visible", shouldShow);
-    if (shouldShow) {
+  setVisibility(plugin, overlay, overlayDisplayState) {
+    overlay.classList.toggle("visible", overlayDisplayState != OVERLAY_DISPLAY_HIDDEN);
+    overlay.classList.toggle("minimal", overlayDisplayState == OVERLAY_DISPLAY_MINIMAL)
+    if (overlayDisplayState == OVERLAY_DISPLAY_VISIBLE) {
       overlay.removeAttribute("dismissed");
     }
   },
 
   /**
    * Check whether the plugin should be visible on the page. A plugin should
    * not be visible if the overlay is too big, or if any other page content
    * overlays it.
    *
    * This function will handle showing or hiding the overlay.
    * @returns true if the plugin is invisible.
    */
-  shouldShowOverlay(plugin, overlay) {
+  computeOverlayDisplayState(plugin, overlay) {
+    let fallbackType = plugin.pluginFallbackType;
+    if (plugin.pluginFallbackTypeOverride !== undefined) {
+      fallbackType = plugin.pluginFallbackTypeOverride;
+    }
+    if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET) {
+      return OVERLAY_DISPLAY_HIDDEN;
+    }
+
     // If the overlay size is 0, we haven't done layout yet. Presume that
     // plugins are visible until we know otherwise.
     if (overlay.scrollWidth == 0) {
-      return true;
+      return OVERLAY_DISPLAY_VISIBLE;
     }
 
     // Is the <object>'s size too small to hold what we want to show?
     let pluginRect = plugin.getBoundingClientRect();
     // XXX bug 446693. The text-shadow on the submitted-report text at
     //     the bottom causes scrollHeight to be larger than it should be.
     let overflows = (overlay.scrollWidth > Math.ceil(pluginRect.width)) ||
                     (overlay.scrollHeight - 5 > Math.ceil(pluginRect.height));
     if (overflows) {
-      return false;
+      return OVERLAY_DISPLAY_MINIMAL;
     }
 
     // Is the plugin covered up by other content so that it is not clickable?
     // Floating point can confuse .elementFromPoint, so inset just a bit
     let left = pluginRect.left + 2;
     let right = pluginRect.right - 2;
     let top = pluginRect.top + 2;
     let bottom = pluginRect.bottom - 2;
@@ -335,21 +348,21 @@ PluginContent.prototype = {
                            .getInterface(Ci.nsIDOMWindowUtils);
 
     for (let [x, y] of points) {
       if (x < 0 || y < 0) {
         continue;
       }
       let el = cwu.elementFromPoint(x, y, true, true);
       if (el === plugin) {
-        return true;
+        return OVERLAY_DISPLAY_VISIBLE;
       }
     }
 
-    return false;
+    return OVERLAY_DISPLAY_HIDDEN;
   },
 
   addLinkClickCallback(linkNode, callbackName /* callbackArgs...*/) {
     // XXX just doing (callback)(arg) was giving a same-origin error. bug?
     let self = this;
     let callbackArgs = Array.prototype.slice.call(arguments).slice(2);
     linkNode.addEventListener("click",
                               function(evt) {
@@ -387,16 +400,17 @@ PluginContent.prototype = {
         return "PluginNotFound";
       case Ci.nsIObjectLoadingContent.PLUGIN_DISABLED:
         return "PluginDisabled";
       case Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED:
         return "PluginBlocklisted";
       case Ci.nsIObjectLoadingContent.PLUGIN_OUTDATED:
         return "PluginOutdated";
       case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
+      case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET:
         return "PluginClickToPlay";
       case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
         return "PluginVulnerableUpdatable";
       case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
         return "PluginVulnerableNoUpdate";
       default:
         // Not all states map to a handler
         return null;
@@ -457,17 +471,17 @@ PluginContent.prototype = {
       }
     }
 
     let plugin = event.target;
 
     if (eventType == "PluginPlaceholderReplaced") {
       plugin.removeAttribute("href");
       let overlay = this.getPluginUI(plugin, "main");
-      this.setVisibility(plugin, overlay, true);
+      this.setVisibility(plugin, overlay, OVERLAY_DISPLAY_VISIBLE);
       let inIDOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
                           .getService(Ci.inIDOMUtils);
       // Add psuedo class so our styling will take effect
       inIDOMUtils.addPseudoClassLock(plugin, "-moz-handler-clicktoplay");
       overlay.addEventListener("click", this, true);
       return;
     }
 
@@ -542,20 +556,20 @@ PluginContent.prototype = {
         break;
     }
 
     // Show the in-content UI if it's not too big. The crashed plugin handler already did this.
     let overlay = this.getPluginUI(plugin, "main");
     if (eventType != "PluginCrashed") {
       if (overlay != null) {
         this.setVisibility(plugin, overlay,
-                           this.shouldShowOverlay(plugin, overlay));
+                           this.computeOverlayDisplayState(plugin, overlay));
         let resizeListener = () => {
           this.setVisibility(plugin, overlay,
-            this.shouldShowOverlay(plugin, overlay));
+            this.computeOverlayDisplayState(plugin, overlay));
           this.updateNotificationUI();
         };
         plugin.addEventListener("overflow", resizeListener);
         plugin.addEventListener("underflow", resizeListener);
       }
     }
 
     let closeIcon = this.getPluginUI(plugin, "closeIcon");
@@ -587,17 +601,17 @@ PluginContent.prototype = {
 
     let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
     let permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
     let principal = objLoadingContent.ownerGlobal.top.document.nodePrincipal;
     let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString);
 
     let isFallbackTypeValid =
       objLoadingContent.pluginFallbackType >= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
-      objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
+      objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET;
 
     return !objLoadingContent.activated &&
            pluginPermission != Ci.nsIPermissionManager.DENY_ACTION &&
            isFallbackTypeValid;
   },
 
   hideClickToPlayOverlay(plugin) {
     let overlay = this.getPluginUI(plugin, "main");
@@ -660,17 +674,18 @@ PluginContent.prototype = {
       permissionString = pluginHost.getPermissionStringForType(objLoadingContent.actualType);
     }
 
     let principal = doc.defaultView.top.document.nodePrincipal;
     let pluginPermission = Services.perms.testPermissionFromPrincipal(principal, permissionString);
 
     let overlay = this.getPluginUI(plugin, "main");
 
-    if (pluginPermission == Ci.nsIPermissionManager.DENY_ACTION) {
+    if (pluginPermission == Ci.nsIPermissionManager.DENY_ACTION ||
+        pluginPermission == Ci.nsIObjectLoadingContent.PLUGIN_PERMISSION_PROMPT_ACTION_QUIET) {
       if (overlay) {
         overlay.classList.remove("visible");
       }
       return;
     }
 
     if (overlay) {
       overlay.addEventListener("click", this, true);
@@ -728,35 +743,36 @@ PluginContent.prototype = {
       }
       if (pluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
         let overlay = this.getPluginUI(plugin, "main");
         if (ChromeUtils.getClassName(plugin) === "HTMLAnchorElement") {
           placeHolderFound = true;
         } else {
           pluginFound = true;
         }
-        if (newState == "block") {
+        if (newState == "block" || newState == "blockalways" || newState == "continueblocking") {
           if (overlay) {
             overlay.addEventListener("click", this, true);
           }
+          plugin.pluginFallbackTypeOverride = pluginInfo.fallbackType;
           plugin.reload(true);
         } else if (this.canActivatePlugin(plugin)) {
           if (overlay) {
             overlay.removeEventListener("click", this, true);
           }
           plugin.playPlugin();
         }
       }
     }
 
     // If there are no instances of the plugin on the page any more, what the
     // user probably needs is for us to allow and then refresh. Additionally, if
     // this is content that requires HLS or we replaced the placeholder the page
     // needs to be refreshed for it to insert its plugins
-    if (newState != "block" &&
+    if (newState != "block" && newState != "blockalways" && newState != "continueblocking" &&
        (!pluginFound || placeHolderFound || contentWindow.pluginRequiresReload)) {
       this.reloadPage();
     }
     this.updateNotificationUI();
   },
 
   _showClickToPlayNotification(plugin, showNow) {
     let plugins = [];
@@ -849,16 +865,17 @@ PluginContent.prototype = {
       switch (action.fallbackType) {
         // haveInsecure will trigger the red flashing icon and the infobar
         // styling below
         case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
         case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
           haveInsecure = true;
           // fall through
 
+        case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET:
         case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
           actions.set(action.permissionString, action);
           continue;
       }
     }
 
     // Remove plugins that are already active, or large enough to show an overlay.
     let cwu = this.content.QueryInterface(Ci.nsIInterfaceRequestor)
@@ -872,27 +889,28 @@ PluginContent.prototype = {
       if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
         actions.delete(info.permissionString);
         if (actions.size == 0) {
           break;
         }
         continue;
       }
       if (fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
+          fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET &&
           fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE &&
           fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE) {
         continue;
       }
       let overlay = this.getPluginUI(plugin, "main");
       if (!overlay) {
         continue;
       }
-      let shouldShow = this.shouldShowOverlay(plugin, overlay);
-      this.setVisibility(plugin, overlay, shouldShow);
-      if (shouldShow) {
+      let overlayDisplayState = this.computeOverlayDisplayState(plugin, overlay);
+      this.setVisibility(plugin, overlay, overlayDisplayState);
+      if (overlayDisplayState == OVERLAY_DISPLAY_VISIBLE) {
         actions.delete(info.permissionString);
         if (actions.size == 0) {
           break;
         }
       }
     }
 
     // If there are any items remaining in `actions` now, they are hidden
@@ -1066,31 +1084,31 @@ PluginContent.prototype = {
     this.addLinkClickCallback(helpIcon, "openHelpPage");
 
     let crashText = this.getPluginUI(plugin, "crashedText");
     crashText.textContent = message;
 
     let link = this.getPluginUI(plugin, "reloadLink");
     this.addLinkClickCallback(link, "reloadPage");
 
-    let isShowing = this.shouldShowOverlay(plugin, overlay);
+    let overlayDisplayState = this.computeOverlayDisplayState(plugin, overlay);
 
     // Is the <object>'s size too small to hold what we want to show?
-    if (!isShowing) {
+    if (overlayDisplayState != OVERLAY_DISPLAY_VISIBLE) {
       // First try hiding the crash report submission UI.
       statusDiv.removeAttribute("status");
 
-      isShowing = this.shouldShowOverlay(plugin, overlay);
+      overlayDisplayState = this.computeOverlayDisplayState(plugin, overlay);
     }
-    this.setVisibility(plugin, overlay, isShowing);
+    this.setVisibility(plugin, overlay, overlayDisplayState);
 
     let doc = plugin.ownerDocument;
     let runID = plugin.runID;
 
-    if (isShowing) {
+    if (overlayDisplayState == OVERLAY_DISPLAY_VISIBLE) {
       // If a previous plugin on the page was too small and resulted in adding a
       // notification bar, then remove it because this plugin instance it big
       // enough to serve as in-content notification.
       this.hideNotificationBar("plugin-crashed");
       doc.mozNoPluginCrashedNotification = true;
 
       // Notify others that the crash reporter UI is now ready.
       // Currently, this event is only used by tests.
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -554,22 +554,22 @@ toolbarpaletteitem[place=toolbar] > tool
   padding: 5px 12px;
 }
 
 #downloads-button-autohide-checkbox {
   margin: 0;
   padding: 0;
 }
 
-#ready-player-one {
+#whimsy-button {
   /* Don't need HiDPI versions since the size used will be scaled down to 20x20. */
   list-style-image: url("chrome://browser/skin/customizableui/whimsy.png");
 }
 
-#ready-player-one > .button-box > .button-icon {
+#whimsy-button > .button-box > .button-icon {
   width: 16px;
   height: 16px;
 }
 
 #customization-palette[whimsypong] {
   /* Keep the palette in the render tree but invisible
      so -moz-element() will work. */
   padding: 0;
@@ -639,8 +639,28 @@ toolbarpaletteitem[place=toolbar] > tool
 
 #lives[lives="2"] {
   height: 40px;
 }
 
 #lives[lives="1"] {
   height: 20px;
 }
+
+#customization-pong-arena[lives="0"] > #ball {
+  animation: game-over 4s forwards ease;
+}
+
+@keyframes game-over {
+  15% {
+    transform: scale(2) translateY(-10px) rotateZ(-90deg);
+  }
+  35% {
+    opacity: 1;
+  }
+  65% {
+    opacity: 0;
+  }
+  100% {
+    transform: scale(2) translateY(300px) rotateZ(-2.5turn);
+    opacity: 0;
+  }
+}
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -208,35 +208,35 @@ html|*#webRTC-previewVideo {
 
 .popup-notification-icon[popupid="addon-install-complete"] {
   list-style-image: url(chrome://browser/skin/addons/addon-install-installed.svg);
 }
 
 .popup-notification-icon[popupid="addon-install-restart"] {
   list-style-image: url(chrome://browser/skin/addons/addon-install-restart.svg);
 }
-
-.popup-notification-icon[popupid="click-to-play-plugins"] {
-  list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked.svg);
-}
-
 /* OFFLINE APPS */
 
 .popup-notification-icon[popupid*="offline-app-requested"],
 .popup-notification-icon[popupid="offline-app-usage"] {
   list-style-image: url(chrome://global/skin/icons/question-64.png);
 }
 
 /* PLUGINS */
 
 .plugin-icon {
   list-style-image: url(chrome://browser/skin/notification-icons/plugin.svg);
   transition: fill 1.5s;
 }
 
+.plugin-blocked-icon {
+  list-style-image: url(chrome://browser/skin/notification-icons/plugin-blocked.svg);
+  transition: fill 1.5s;
+}
+
 #plugin-icon-badge {
   list-style-image: url(chrome://browser/skin/notification-icons/plugin-badge.svg);
   opacity: 0;
   transition: opacity 1.5s;
 }
 
 #plugins-notification-icon[extraAttr="inactive"] > .plugin-icon {
   fill: #bfbfbf;
--- a/browser/themes/shared/plugin-doorhanger.inc.css
+++ b/browser/themes/shared/plugin-doorhanger.inc.css
@@ -1,62 +1,8 @@
-#notification-popup[popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowcontent {
-  padding: 0px;
-}
-
-.click-to-play-plugins-notification-center-box {
-  border: 1px solid ThreeDShadow;
-  margin: 10px;
-}
-
-.plugin-popupnotification-centeritem:nth-child(odd) {
-  background-color: rgba(0,0,0,0.1);
-}
-
-.center-item-label {
-  margin-inline-start: 6px;
-  margin-bottom: 0;
-  text-overflow: ellipsis;
-}
-
-.center-item-warning-icon {
-  background-image: url("chrome://mozapps/skin/extensions/alerticon-info-negative.svg");
-  background-repeat: no-repeat;
-  width: 16px;
-  height: 15px;
-  margin-inline-start: 6px;
-}
-
-.click-to-play-plugins-notification-button-container {
-  background-color: var(--arrowpanel-dimmed);
-  margin-top: 5px;
-  display: flex;
-}
-
-.click-to-play-popup-button {
-  width: 50%;
-}
-
-.click-to-play-plugins-notification-description-box {
-  padding: 10px;
-}
-
-.click-to-play-plugins-outer-description {
-  margin-top: 8px;
-}
-
-.click-to-play-plugins-notification-link,
-.center-item-link {
-  margin: 0;
-}
-
-.click-to-play-plugins-notification-main-box {
-  width: 100%;
-}
-
 .messageImage[value="plugin-hidden"] {
   list-style-image: url(chrome://browser/skin/notification-icons/plugin.svg);
 }
 
 /* Keep any changes to this style in sync with pluginProblem.css */
 notification.pluginVulnerable {
   background-color: rgb(72,72,72);
   background-image: url(chrome://mozapps/skin/plugins/contentPluginStripe.png);
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -111,16 +111,17 @@ class RemoteAutomation(Automation):
         """
         proc.utilityPath = utilityPath
         # maxTime is used to override the default timeout, we should honor that
         status = proc.wait(timeout = maxTime, noOutputTimeout = timeout)
         self.lastTestSeen = proc.getLastTestSeen
 
         topActivity = self._devicemanager.getTopActivity()
         if topActivity == proc.procName:
+            print "Browser unexpectedly found running. Killing..."
             proc.kill(True)
         if status == 1:
             if maxTime:
                 print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
                       "allowed maximum time of %s seconds" % (self.lastTestSeen, maxTime)
             else:
                 print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
                       "allowed maximum time" % (self.lastTestSeen)
@@ -401,16 +402,19 @@ class RemoteAutomation(Automation):
                 if datetime.datetime.now() > endTime:
                     status = 1
                     break
                 if (noOutputTimeout and noOutputTimer > noOutputTimeout):
                     status = 2
                     break
                 if not hasOutput:
                     top = self.dm.getTopActivity()
+                    if top == "":
+                        print "Failed to get top activity, retrying, once..."
+                        top = self.dm.getTopActivity()
             # Flush anything added to stdout during the sleep
             self.read_stdout()
             return status
 
         def kill(self, stagedShutdown = False):
             if self.utilityPath:
                 # Take a screenshot to capture the screen state just before
                 # the application is killed. There are on-device screenshot
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -186,17 +186,17 @@ def virtualenv_python(env_python, build_
             python = mozconfig['vars']['modified']['PYTHON'][1]
 
     with LineIO(lambda l: log.error(l)) as out:
         verify_python_version(out)
     topsrcdir, topobjdir = build_env.topsrcdir, build_env.topobjdir
     if topobjdir.endswith('/js/src'):
         topobjdir = topobjdir[:-7]
 
-    with LineIO(lambda l: log.info(l)) as out:
+    with LineIO(lambda l: log.info(l), 'replace') as out:
         manager = VirtualenvManager(
             topsrcdir, topobjdir,
             os.path.join(topobjdir, '_virtualenv'), out,
             os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt'))
 
     if python:
         # If we're not in the virtualenv, we need the which module for
         # find_program.
--- a/build/moz.configure/pkg.configure
+++ b/build/moz.configure/pkg.configure
@@ -69,17 +69,17 @@ def pkg_check_modules(var, package_desc,
             try:
                 subprocess.check_output([pkg_config, '--errors-to-stdout',
                                          '--print-errors', package_desc])
                 log.info("yes")
                 return True
             except subprocess.CalledProcessError as e:
                 log.info("no")
                 log_writer = log.warning if allow_missing else log.error
-                with LineIO(lambda l: log_writer(l)) as o:
+                with LineIO(lambda l: log_writer(l), 'replace') as o:
                     o.write(e.output)
                 if not allow_missing:
                     sys.exit(1)
 
     @depends(pkg_config, package_desc, when=package)
     @checking('%s_CFLAGS' % var, callback=lambda t: ' '.join(t))
     def pkg_cflags(pkg_config, package_desc):
         flags = check_cmd_output(pkg_config, '--cflags', package_desc)
--- a/build/moz.configure/util.configure
+++ b/build/moz.configure/util.configure
@@ -58,17 +58,17 @@ def check_cmd_output(*args, **kwargs):
         if retcode == 0:
             return stdout
 
         log.debug('The command returned non-zero exit status %d.',
                   retcode)
         for out, desc in ((stdout, 'output'), (stderr, 'error output')):
             if out:
                 log.debug('Its %s was:', desc)
-                with LineIO(lambda l: log.debug('| %s', l)) as o:
+                with LineIO(lambda l: log.debug('| %s', l), 'replace') as o:
                     o.write(out)
         if onerror:
             return onerror()
         die('Command `%s` failed with exit status %d.' %
             (quote(*args), retcode))
 
 
 @imports('os')
--- a/config/config.mk
+++ b/config/config.mk
@@ -250,40 +250,24 @@ INCLUDES = \
 include $(MOZILLA_DIR)/config/static-checking-config.mk
 
 LDFLAGS		= $(OS_LDFLAGS) $(MOZBUILD_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
 
 ifdef MOZ_OPTIMIZE
 LDFLAGS		+= $(MOZ_OPTIMIZE_LDFLAGS)
 endif # MOZ_OPTIMIZE
 
-HOST_CFLAGS	+= $(_DEPEND_CFLAGS)
-HOST_CXXFLAGS	+= $(_DEPEND_CFLAGS)
-ifdef CROSS_COMPILE
-HOST_CFLAGS	+= $(HOST_OPTIMIZE_FLAGS)
-HOST_CXXFLAGS	+= $(HOST_OPTIMIZE_FLAGS)
-else
-ifdef MOZ_OPTIMIZE
-HOST_CFLAGS	+= $(MOZ_OPTIMIZE_FLAGS)
-HOST_CXXFLAGS	+= $(MOZ_OPTIMIZE_FLAGS)
-endif # MOZ_OPTIMIZE
-endif # CROSS_COMPILE
-
 COMPILE_CFLAGS	= $(COMPUTED_CFLAGS) $(PGO_CFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE_DEFINES)
 COMPILE_CXXFLAGS = $(COMPUTED_CXXFLAGS) $(PGO_CFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE_DEFINES)
 COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS)
 COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS)
 ASFLAGS += $(MOZBUILD_ASFLAGS)
 
-ifndef CROSS_COMPILE
-HOST_CFLAGS += $(RTL_FLAGS)
-endif
-
-HOST_CFLAGS += $(HOST_DEFINES) $(MOZBUILD_HOST_CFLAGS)
-HOST_CXXFLAGS += $(HOST_DEFINES) $(MOZBUILD_HOST_CXXFLAGS)
+HOST_CFLAGS = $(COMPUTED_HOST_CFLAGS) $(_DEPEND_CFLAGS)
+HOST_CXXFLAGS = $(COMPUTED_HOST_CXXFLAGS) $(_DEPEND_CFLAGS)
 
 # We only add color flags if neither the flag to disable color
 # (e.g. "-fno-color-diagnostics" nor a flag to control color
 # (e.g. "-fcolor-diagnostics=never") is present.
 define colorize_flags
 ifeq (,$(filter $(COLOR_CFLAGS:-f%=-fno-%),$$(1))$(findstring $(COLOR_CFLAGS),$$(1)))
 $(1) += $(COLOR_CFLAGS)
 endif
--- a/devtools/client/debugger/new/README.mozilla
+++ b/devtools/client/debugger/new/README.mozilla
@@ -1,11 +1,11 @@
 This is the debugger.html project output.
 See https://github.com/devtools-html/debugger.html
 
-Taken from upstream commit: aa6b25cc7dc645b8c1d76af58b99012e40b80848
+Taken from upstream commit: d9f18b2cd0792de70289d4dcde5ed3e38be87cf1
 
 Packages:
 - babel-plugin-transform-es2015-modules-commonjs @6.26.0
 - babel-preset-react @6.24.1
 - react @15.6.2
 - react-dom @15.6.2
-- webpack @3.7.1
+- webpack @3.8.1
--- a/devtools/client/debugger/new/debugger.css
+++ b/devtools/client/debugger/new/debugger.css
@@ -421,25 +421,39 @@ body {
   left: 0;
   transition: z-index 200ms;
   z-index: 100;
 }
 
 .modal {
   width: 80%;
   height: auto;
-  overflow-y: scroll;
+  overflow-y: auto;
   background-color: var(--theme-toolbar-background);
   transition: transform 150ms cubic-bezier(0.07, 0.95, 0, 1);
   box-shadow: 1px 1px 3px 1px var(--popup-shadow-color);
 }
 
+.modal .input-wrapper {
+  display: flex;
+  justify-content: center;
+}
+
+.modal .close-btn {
+  padding: 6px;
+}
+
+.modal .result-list {
+  height: calc(100% - 28px);
+  overflow-y: auto;
+}
+
 .modal.entering,
 .modal.exited {
-  transform: translateY(-250px);
+  transform: translateY(-101%);
 }
 
 .modal.entered,
 .modal.exiting {
   transform: translateY(5px);
 }
 
 /* This rule is active when the screen is not short and narrow */
@@ -904,57 +918,79 @@ menuseparator {
  * events. This is good for performance during splitter
  * bar dragging.
  */
 .split-box.dragging > .controlled,
 .split-box.dragging > .uncontrolled {
   pointer-events: none;
 }
 .arrow,
-.folder,
-.domain,
-.file,
 .worker,
 .refresh,
 .shortcut,
 .add-button {
   fill: var(--theme-splitter-color);
 }
 
+.file,
+.folder,
+.domain {
+  background-color: var(--theme-splitter-color);
+}
+
 .worker,
 .folder {
   position: relative;
   top: 2px;
 }
 
 .domain,
 .file,
 .worker,
 .refresh,
 .add-button {
   position: relative;
   top: 1px;
 }
 
-.domain svg,
-.folder svg,
 .worker svg,
 .refresh svg,
 .shortcut svg,
 .add-button svg {
   width: 15px;
 }
 
-.file svg {
+img.domain,
+img.folder {
+  width: 15px;
+  height: 15px;
+}
+
+img.domain {
+  mask: url("chrome://devtools/skin/images/debugger/domain.svg") no-repeat;
+}
+
+img.folder {
+  mask: url("chrome://devtools/skin/images/debugger/folder.svg") no-repeat;
+}
+
+img.file {
+  mask: url("chrome://devtools/skin/images/debugger/file.svg") no-repeat;
   width: 13px;
-}
-
-.file svg,
-.domain svg,
-.folder svg,
+  height: 13px;
+}
+
+img.domain,
+img.folder,
+img.file {
+  mask-size: 100%;
+  margin-inline-end: 5px;
+  display: inline-block;
+}
+
 .refresh svg,
 .shortcut svg,
 .worker svg {
   margin-inline-end: 5px;
 }
 
 img.arrow {
   mask: url("chrome://devtools/skin/images/debugger/arrow.svg");
@@ -1276,164 +1312,28 @@ html[dir="rtl"] .managed-tree .tree .nod
 .project-text-search .managed-tree {
   overflow-y: auto;
   height: calc(100% - 81px);
 }
 
 .project-text-search .managed-tree .tree {
   height: 100%;
 }
-.autocomplete {
-  position: relative;
-  width: 100%;
-  height: 100%;
-}
-
-.autocomplete .no-result-msg {
-  color: var(--theme-body-color-inactive);
-  font-size: 24px;
-  padding: 4px;
-  word-break: break-all;
-}
-.result-list {
-  list-style: none;
-  margin: 0px;
-  padding: 0px;
-  overflow: auto;
-  width: calc(100% - 1px); /* 1px fixes the hidden right border */
-}
-
-.result-list.big {
-  max-height: calc(100% - 32px);
-}
-
-.result-list * {
-  -moz-user-select: none;
-  user-select: none;
-}
-
-.result-list li {
-  color: var(--theme-body-color);
-  padding: 4px 13px;
-  display: flex;
-  justify-content: space-between;
-  border: 1px solid transparent;
-}
-
-.result-list.big li {
-  padding: 10px;
-  flex-direction: column;
-  border-bottom: 1px solid var(--theme-splitter-color);
-}
-
-.result-list li:hover {
-  background: var(--theme-tab-toolbar-background);
-}
-
-.result-list li.selected {
-  border-color: var(--theme-selection-background);
-}
-
-.result-list.small li.selected {
-  background-color: var(--theme-selection-background);
-  color: white;
-}
-
-.theme-dark .result-list.small li.selected {
-  background-color: var(--theme-body-background);
-}
-
-.theme-dark .result-list li:hover {
-  background: var(--grey-70);
-}
-
-.theme-dark .result-list li.selected {
-  background: var(--grey-70);
-}
-
-.result-list li .title {
-  line-height: 1.5em;
-  word-break: break-all;
-}
-
-.result-list li.selected .title {
-  color: white;
-}
-
-.result-list.big li.selected .title {
-  color: var(--theme-body-color);
-}
-
-.result-list.big li .subtitle {
-  word-break: break-all;
-  color: var(--theme-body-color-inactive);
-}
-
-.result-list.big li .subtitle {
-  line-height: 1.5em;
-}
-
-.search-bar .result-list li.selected .subtitle {
-  color: white;
-}
-
-.search-bar .result-list {
-  border-bottom: 1px solid var(--theme-splitter-color);
-}
-
-.theme-dark .result-list {
-  background-color: var(--theme-body-background);
-}
 .search-container {
   position: absolute;
   top: 30px;
   left: 0;
   width: calc(100% - 1px);
   height: calc(100% - 31px);
   display: flex;
   flex-direction: column;
   z-index: 20;
   background-color: var(--theme-body-background);
   overflow-y: hidden;
 }
-
-.searchinput-container {
-  display: flex;
-  border-bottom: 1px solid var(--theme-splitter-color);
-}
-
-.theme-dark .result-list li .subtitle {
-  color: var(--theme-comment-alt);
-}
-
-.toggle-search {
-  background-color: var(--theme-toolbar-background);
-  border-bottom: 1px solid var(--theme-splitter-color);
-  color: var(--theme-comment-alt);
-  display: flex;
-  flex-shrink: 0;
-  justify-content: flex-start;
-  line-height: 40px;
-  padding: 0 13px;
-  width: calc(100% - 1px);
-}
-
-.toggle-search .title {
-  font-weight: 500;
-  font-size: 120%;
-}
-
-.toggle-search .text {
-  margin-left: 1em;
-  cursor: default;
-}
-
-.toggle-search .active {
-  color: var(--theme-selection-background);
-}
 .sources-panel {
   background-color: var(--theme-sidebar-background);
   display: flex;
   flex: 1;
   flex-direction: column;
   overflow: hidden;
   position: relative;
 }
@@ -1556,16 +1456,43 @@ html[dir="rtl"] .managed-tree .tree .nod
   background-color: var(--theme-body-background);
   border-bottom-color: transparent;
 }
 
 .source-outline-tabs .tab.active path,
 .source-outline-tabs .tab:hover path {
   fill: var(--theme-body-color);
 }
+
+.sources-list .managed-tree .tree .node img.blackBox {
+  mask: url("chrome://devtools/skin/images/debugger/blackBox.svg") no-repeat;
+  mask-size: 100%;
+  background-color: var(--theme-highlight-blue);
+  width: 13px;
+  height: 13px;
+  display: inline-block;
+  margin-inline-end: 5px;
+  margin-bottom: -2px;
+}
+
+.sources-list .managed-tree .tree .node.focused img.blackBox {
+  background-color: white;
+}
+
+.theme-dark .sources-list .managed-tree .tree .node:not(.focused) img.blackBox {
+  background-color: var(--theme-content-color3);
+}
+
+.theme-dark .sources-list .managed-tree .tree .node img.blackBox {
+  background-color: var(--theme-body-color);
+}
+
+.theme-dark .sources-list .managed-tree .tree .node.focused img.blackBox {
+  background-color: white;
+}
 .outline {
   overflow-y: auto;
 }
 
 .outline .outline-pane-info {
   width: 100%;
   font-style: italic;
   text-align: center;
@@ -1624,17 +1551,17 @@ html[dir="rtl"] .managed-tree .tree .nod
 
 .function-signature .comma {
   color: var(--object-color);
 }
 .toggle-button-start,
 .toggle-button-end {
   transform: translate(0, 0px);
   transition: transform 0.25s ease-in-out;
-  padding: 5px 5px;
+  padding: 5px;
 }
 
 .toggle-button-start.vertical,
 .toggle-button-end.vertical {
   padding: 2.5px 2.5px;
 }
 
 .toggle-button-start svg,
@@ -1672,17 +1599,17 @@ html .toggle-button-end.vertical svg {
 }
 .source-footer {
   background: var(--theme-body-background);
   border-top: 1px solid var(--theme-splitter-color);
   position: absolute;
   display: flex;
   bottom: 0;
   left: 0;
-  right: 1px;
+  right: 0;
   opacity: 1;
   z-index: 1;
   -moz-user-select: none;
   user-select: none;
   height: var(--editor-footer-height);
   box-sizing: border-box;
 }
 
@@ -1773,17 +1700,17 @@ html .toggle-button-end.vertical svg {
 .search-bottom-bar * {
   -moz-user-select: none;
   user-select: none;
 }
 
 .search-bottom-bar {
   display: flex;
   flex-shrink: 0;
-  justify-content: space-between;
+  justify-content: flex-end;
   width: calc(100% - 1px);
   height: var(--editor-second-searchbar-height);
   background-color: var(--theme-toolbar-background);
   border-bottom: 1px solid var(--theme-splitter-color);
   padding: 0 13px;
 }
 
 .search-bottom-bar button:focus {
@@ -2393,16 +2320,18 @@ html[dir="rtl"] .arrow svg,
 .conditional-breakpoint-panel input:focus {
   outline-width: 0;
 }
 .editor-wrapper {
   --debug-line-border: rgb(145, 188, 219);
   --debug-expression-background: rgba(202, 227, 255, 0.5);
   --editor-searchbar-height: 27px;
   --editor-second-searchbar-height: 27px;
+  --debug-line-error-border: rgb(255, 0, 0);
+  --debug-expression-error-background: rgba(231, 116, 113, 0.3);
 }
 
 .theme-dark .editor-wrapper {
   --debug-expression-background: #54617e;
   --debug-line-border: #7786a2;
 }
 
 .editor-wrapper .CodeMirror-linewidget {
@@ -2418,18 +2347,18 @@ html[dir="rtl"] .arrow svg,
 }
 
 /**
  * There's a known codemirror flex issue with chrome that this addresses.
  * BUG https://github.com/devtools-html/debugger.html/issues/63
  */
 .editor-wrapper {
   position: absolute;
-  height: calc(100% - 31px);
-  width: calc(100% - 1.5px);
+  height: calc(100% - 29px);
+  width: calc(100% - 1px);
   top: 29px;
   left: 0px;
   --editor-footer-height: 24px;
 }
 
 html[dir="rtl"] .editor-mount {
   direction: ltr;
 }
@@ -2510,19 +2439,18 @@ html[dir="rtl"] .editor-mount {
 }
 
 .editor-wrapper .editor-mount {
   width: 100%;
   background-color: var(--theme-body-background);
 }
 
 .CodeMirror-linenumber {
-  font-size: 12px;
-  line-height: 15px;
-  font-family: monospace;
+  font-size: 11px;
+  line-height: 14px;
 }
 
 .folding-enabled .CodeMirror-linenumber {
   text-align: left;
   padding: 0 0 0 2px;
 }
 
 /* set the linenumber white when there is a breakpoint */
@@ -2542,27 +2470,42 @@ html[dir="rtl"] .editor-mount {
 .theme-dark .editor-wrapper .CodeMirror-line .cm-comment {
   color: var(--theme-content-color3);
 }
 
 .debug-expression {
   background-color: var(--debug-expression-background);
 }
 
+debug-expression-error {
+  background-color: var(--debug-expression-error-background);
+}
+
 .new-debug-line .CodeMirror-line {
   background-color: transparent !important;
   outline: var(--debug-line-border) solid 1px;
 }
 
 /* Don't display the highlight color since the debug line
    is already highlighted */
 .new-debug-line .CodeMirror-activeline-background {
   display: none;
 }
 
+.new-debug-line-error .CodeMirror-line {
+  background-color: var(--debug-expression-error-background) !important;
+  outline: var(--debug-line-error-border) solid 1px;
+}
+
+/* Don't display the highlight color since the debug line
+  is already highlighted */
+.new-debug-line-error .CodeMirror-activeline-background {
+  display: none;
+}
+
 .highlight-line .CodeMirror-line {
   animation: fade-highlight-out 1.5s normal forwards;
 }
 
 @keyframes fade-highlight-out {
   0% {
     background-color: var(--theme-highlight-gray);
   }
@@ -2992,28 +2935,28 @@ html .breakpoints-list .breakpoint.pause
 
 .event-listeners .listener .close {
   display: none;
 }
 
 .event-listeners .listener:hover .close {
   display: block;
 }
-.workers-list * {
-  user-select: none;
-}
-
-.workers-list .worker {
-  font-size: 12px;
-  color: var(--theme-content-color1);
-  padding: 0.5em 1em 0.5em 0.5em;
-  line-height: 1em;
-  position: relative;
-  transition: all 0.25s ease;
-}
+.workers-list * {
+  user-select: none;
+}
+
+.workers-list .worker {
+  font-size: 12px;
+  color: var(--theme-content-color1);
+  padding: 0.5em 1em 0.5em 0.5em;
+  line-height: 1em;
+  position: relative;
+  transition: all 0.25s ease;
+}
 :root {
   --accordion-header-background: var(--theme-toolbar-background);
 }
 
 :root.theme-dark {
   --accordion-header-background: #141416;
 }
 
@@ -3119,55 +3062,83 @@ html[dir="rtl"] .command-bar {
   background: var(--theme-toolbar-background-hover);
 }
 
 :root.theme-dark .command-bar > button {
   color: var(--theme-body-color);
 }
 
 .command-bar > button {
-  margin-inline-end: 0.7em;
+  margin-inline-end: 0.3em;
 }
 
 .command-bar > button:focus {
   outline: none;
 }
 
 html .command-bar > button:disabled {
   opacity: 0.8;
   cursor: default;
 }
 
-.command-bar > button > i {
-  height: 100%;
-  width: 100%;
-  display: block;
-}
-
-.command-bar > button > i > svg {
+img.pause,
+img.stepOver,
+img.stepIn,
+img.stepOut,
+img.resume {
+  background-color: var(--theme-body-color);
+}
+
+.command-bar > button > img {
   width: 16px;
   height: 16px;
-}
-
-.command-bar button.pause-exceptions {
-  margin-inline-start: 0.5em;
+  display: inline-block;
+}
+
+.command-bar > button > img.pause {
+  mask: url("chrome://devtools/skin/images/debugger/pause.svg") no-repeat;
+}
+
+.command-bar > button > img.stepOver {
+  mask: url("chrome://devtools/skin/images/debugger/stepOver.svg") no-repeat;
+}
+
+.command-bar > button > img.stepIn {
+  mask: url("chrome://devtools/skin/images/debugger/stepIn.svg") no-repeat;
+}
+
+.command-bar > button > img.stepOut {
+  mask: url("chrome://devtools/skin/images/debugger/stepOut.svg") no-repeat;
+}
+
+.command-bar > button > img.resume {
+  mask: url("chrome://devtools/skin/images/debugger/resume.svg") no-repeat;
+}
+
+.command-bar > button.pause-exceptions.uncaught.enabled > img.pause-exceptions {
+  background-color: var(--theme-highlight-purple);
+}
+
+.command-bar > button.pause-exceptions.all.enabled > img.pause-exceptions {
+  background-color: var(--theme-highlight-blue);
+}
+
+.command-bar > button.pause-exceptions.enabled > img.pause-exceptions {
+  background-color: var(--theme-body-color);
+}
+
+.command-bar > button > img.pause-exceptions {
+  mask: url("chrome://devtools/skin/images/debugger/pause-exceptions.svg") no-repeat;
+  margin-inline-start: 0.2em;
 }
 
 .command-bar .subSettings {
   float: right;
 }
 
-.command-bar button.pause-exceptions.uncaught {
-  color: var(--theme-highlight-purple);
-}
-
-.command-bar button.pause-exceptions.all {
-  color: var(--theme-highlight-blue);
-}
-
 .bottom {
   border-bottom: none;
   background-color: var(--theme-body-background);
   border-top: 1px solid var(--theme-splitter-color);
   flex: 0 0 27px;
 }
 
 .command-bar > button {
@@ -3211,17 +3182,17 @@ html .command-bar > button:disabled {
 .scopes-pane {
   overflow: auto;
 }
 
 .scopes-list .function-signature {
   display: inline-block;
 }
 .secondary-panes {
-  overflow: scroll;
+  overflow: auto;
   display: flex;
   flex-direction: column;
   flex: 1;
   white-space: nowrap;
   --breakpoint-expression-right-clear-space: 36px;
 }
 
 /*
@@ -3387,16 +3358,20 @@ html .welcomebox .toggle-button-end.coll
   min-width: 40px;
   overflow: hidden;
   padding: 5px;
   margin-inline-start: 3px;
   margin-top: 3px;
   cursor: default;
 }
 
+.source-tab:first-child {
+  margin-inline-start: 0;
+}
+
 .source-tab:hover {
   background-color: var(--theme-toolbar-background-alt);
   border-color: var(--theme-splitter-color);
 }
 
 .source-tab.active {
   color: var(--theme-body-color);
   background-color: var(--theme-body-background);
@@ -3522,39 +3497,97 @@ html[dir="rtl"] .dropdown {
   position: fixed;
   width: 100%;
   height: 100%;
   background: transparent;
   z-index: 999;
   left: 0;
   top: 0;
 }
-.symbol-modal-wrapper {
-  position: fixed;
-  width: 100%;
-  height: 100%;
-  z-index: 9;
-}
-
-.symbol-modal {
-  position: absolute;
-  left: calc(50% - 250px);
-  z-index: 10;
-  width: 500px;
-  height: 230px;
-  background-color: var(--theme-codemirror-gutter-background);
-  top: 30px;
-}
-
-.symbol-modal .input-wrapper,
-.modal .input-wrapper {
+.result-list {
+  list-style: none;
+  margin: 0px;
+  padding: 0px;
+  overflow: auto;
+  width: calc(100% - 1px); /* 1px fixes the hidden right border */
+}
+
+.result-list * {
+  -moz-user-select: none;
+  user-select: none;
+}
+
+.result-list li {
+  color: var(--theme-body-color);
+  padding: 4px 13px;
   display: flex;
-  justify-content: center;
-}
-
-.modal .close-btn {
-  padding: 6px;
-}
-
-.modal .result-list {
-  height: calc(100% - 28px);
-  overflow-y: auto;
-}
+  justify-content: space-between;
+  border: 1px solid transparent;
+}
+
+.result-list.big li {
+  padding: 10px;
+  flex-direction: column;
+  border-bottom: 1px solid var(--theme-splitter-color);
+}
+
+.result-list li:hover {
+  background: var(--theme-tab-toolbar-background);
+}
+
+.result-list li.selected {
+  border-color: var(--theme-selection-background);
+}
+
+.result-list.small li.selected {
+  background-color: var(--theme-selection-background);
+  color: white;
+}
+
+.theme-dark .result-list.small li.selected {
+  background-color: var(--theme-body-background);
+}
+
+.theme-dark .result-list li:hover {
+  background: var(--grey-70);
+}
+
+.theme-dark .result-list li.selected {
+  background: var(--grey-70);
+}
+
+.result-list li .title {
+  line-height: 1.5em;
+  word-break: break-all;
+}
+
+.result-list li.selected .title {
+  color: white;
+}
+
+.result-list.big li.selected .title {
+  color: var(--theme-body-color);
+}
+
+.result-list.big li .subtitle {
+  word-break: break-all;
+  color: var(--theme-body-color-inactive);
+}
+
+.result-list.big li .subtitle {
+  line-height: 1.5em;
+}
+
+.theme-dark .result-list.big li .subtitle {
+  color: var(--theme-comment-alt);
+}
+
+.search-bar .result-list li.selected .subtitle {
+  color: white;
+}
+
+.search-bar .result-list {
+  border-bottom: 1px solid var(--theme-splitter-color);
+}
+
+.theme-dark .result-list {
+  background-color: var(--theme-body-background);
+}
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -12998,65 +12998,65 @@ module.exports = __WEBPACK_EXTERNAL_MODU
 /* 787 */,
 /* 788 */,
 /* 789 */,
 /* 790 */,
 /* 791 */,
 /* 792 */
 /***/ (function(module, exports) {
 
-var g;
-
-// This works in non-strict mode
-g = (function() {
-	return this;
-})();
-
-try {
-	// This works if eval is allowed (see CSP)
-	g = g || Function("return this")() || (1,eval)("this");
-} catch(e) {
-	// This works if the window reference is available
-	if(typeof window === "object")
-		g = window;
-}
-
-// g can still be undefined, but nothing to do about it...
-// We return undefined, instead of nothing here, so it's
-// easier to handle this case. if(!global) { ...}
-
-module.exports = g;
+var g;
+
+// This works in non-strict mode
+g = (function() {
+	return this;
+})();
+
+try {
+	// This works if eval is allowed (see CSP)
+	g = g || Function("return this")() || (1,eval)("this");
+} catch(e) {
+	// This works if the window reference is available
+	if(typeof window === "object")
+		g = window;
+}
+
+// g can still be undefined, but nothing to do about it...
+// We return undefined, instead of nothing here, so it's
+// easier to handle this case. if(!global) { ...}
+
+module.exports = g;
 
 
 /***/ }),
 /* 793 */
 /***/ (function(module, exports) {
 
-module.exports = function(module) {
-	if(!module.webpackPolyfill) {
-		module.deprecate = function() {};
-		module.paths = [];
-		// module.parent = undefined by default
-		if(!module.children) module.children = [];
-		Object.defineProperty(module, "loaded", {
-			enumerable: true,
-			get: function() {
-				return module.l;
-			}
-		});
-		Object.defineProperty(module, "id", {
-			enumerable: true,
-			get: function() {
-				return module.i;
-			}
-		});
-		module.webpackPolyfill = 1;
-	}
-	return module;
-};
+module.exports = function(module) {
+	if(!module.webpackPolyfill) {
+		module.deprecate = function() {};
+		module.paths = [];
+		// module.parent = undefined by default
+		if(!module.children) module.children = [];
+		Object.defineProperty(module, "loaded", {
+			enumerable: true,
+			get: function() {
+				return module.l;
+			}
+		});
+		Object.defineProperty(module, "id", {
+			enumerable: true,
+			get: function() {
+				return module.i;
+			}
+		});
+		module.webpackPolyfill = 1;
+	}
+	return module;
+};
 
 
 /***/ }),
 /* 794 */,
 /* 795 */,
 /* 796 */,
 /* 797 */,
 /* 798 */,
@@ -14257,17 +14257,17 @@ module.exports = "<svg xmlns=\"http://ww
 /* 955 */,
 /* 956 */,
 /* 957 */,
 /* 958 */,
 /* 959 */,
 /* 960 */
 /***/ (function(module, exports) {
 
-module.exports = "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n# LOCALIZATION NOTE These strings are used inside the Debugger\n# which is available from the Web Developer sub-menu -> 'Debugger'.\n# The correct localization of this file might be to keep it in\n# English, or another language commonly spoken among web developers.\n# You want to make that choice consistent across the developer tools.\n# A good criteria is the language in which you'd find the best\n# documentation on web development on the web.\n\n# LOCALIZATION NOTE (collapsePanes): This is the tooltip for the button\n# that collapses the left and right panes in the debugger UI.\ncollapsePanes=Collapse panes\n\n# LOCALIZATION NOTE (copySource): This is the text that appears in the\n# context menu to copy the selected source of file open.\ncopySource=Copy\ncopySource.accesskey=y\n\n# LOCALIZATION NOTE (copySourceUri2): This is the text that appears in the\n# context menu to copy the source URI of file open.\ncopySourceUri2=Copy source URI\ncopySourceUri2.accesskey=u\n\n# LOCALIZATION NOTE (setDirectoryRoot): This is the text that appears in the\n# context menu to set a directory as root directory\nsetDirectoryRoot.label=Set directory root\nsetDirectoryRoot.accesskey=r\n\n# LOCALIZATION NOTE (copyFunction): This is the text that appears in the\n# context menu to copy the function the user selected\ncopyFunction.label=Copy function\ncopyFunction.accesskey=F\n\n# LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the\n# context menu to copy the stack trace methods, file names and row number.\ncopyStackTrace=Copy stack trace\ncopyStackTrace.accesskey=c\n\n# LOCALIZATION NOTE (expandPanes): This is the tooltip for the button\n# that expands the left and right panes in the debugger UI.\nexpandPanes=Expand panes\n\n# LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause\n# button when the debugger is in a running state.\npauseButtonTooltip=Pause %S\n\n# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for\n# the pause button after it's been clicked but before the next JavaScript to run.\npausePendingButtonTooltip=Waiting for next execution\n\n# LOCALIZATION NOTE (resumeButtonTooltip): The label that is displayed on the pause\n# button when the debugger is in a paused state.\nresumeButtonTooltip=Resume %S\n\n# LOCALIZATION NOTE (stepOverTooltip): The label that is displayed on the\n# button that steps over a function call.\nstepOverTooltip=Step over %S\n\n# LOCALIZATION NOTE (stepInTooltip): The label that is displayed on the\n# button that steps into a function call.\nstepInTooltip=Step in %S\n\n# LOCALIZATION NOTE (stepOutTooltip): The label that is displayed on the\n# button that steps out of a function call.\nstepOutTooltip=Step out %S\n\n# LOCALIZATION NOTE (workersHeader): The text to display in the events\n# header.\nworkersHeader=Workers\n\n# LOCALIZATION NOTE (noWorkersText): The text to display in the workers list\n# when there are no workers.\nnoWorkersText=This page has no workers.\n\n# LOCALIZATION NOTE (noSourcesText): The text to display in the sources list\n# when there are no sources.\nnoSourcesText=This page has no sources.\n\n# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab\n# when there are no events.\nnoEventListenersText=No event listeners to display.\n\n# LOCALIZATION NOTE (eventListenersHeader): The text to display in the events\n# header.\neventListenersHeader=Event listeners\n\n# LOCALIZATION NOTE (noStackFramesText): The text to display in the call stack tab\n# when there are no stack frames.\nnoStackFramesText=No stack frames to display\n\n# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when\n# the user hovers over the checkbox used to toggle an event breakpoint.\neventCheckboxTooltip=Toggle breaking on this event\n\n# LOCALIZATION NOTE (eventOnSelector): The text to display in the events tab\n# for every event item, between the event type and event selector.\neventOnSelector=on\n\n# LOCALIZATION NOTE (eventInSource): The text to display in the events tab\n# for every event item, between the event selector and listener's owner source.\neventInSource=in\n\n# LOCALIZATION NOTE (eventNodes): The text to display in the events tab when\n# an event is listened on more than one target node.\neventNodes=%S nodes\n\n# LOCALIZATION NOTE (eventNative): The text to display in the events tab when\n# a listener is added from plugins, thus getting translated to native code.\neventNative=[native code]\n\n# LOCALIZATION NOTE (*Events): The text to display in the events tab for\n# each group of sub-level event entries.\nanimationEvents=Animation\naudioEvents=Audio\nbatteryEvents=Battery\nclipboardEvents=Clipboard\ncompositionEvents=Composition\ndeviceEvents=Device\ndisplayEvents=Display\ndragAndDropEvents=Drag and Drop\ngamepadEvents=Gamepad\nindexedDBEvents=IndexedDB\ninteractionEvents=Interaction\nkeyboardEvents=Keyboard\nmediaEvents=HTML5 Media\nmouseEvents=Mouse\nmutationEvents=Mutation\nnavigationEvents=Navigation\npointerLockEvents=Pointer Lock\nsensorEvents=Sensor\nstorageEvents=Storage\ntimeEvents=Time\ntouchEvents=Touch\notherEvents=Other\n\n# LOCALIZATION NOTE (blackboxCheckboxTooltip2): The tooltip text to display when\n# the user hovers over the checkbox used to toggle blackboxing its associated\n# source.\nblackboxCheckboxTooltip2=Toggle blackboxing\n\n# LOCALIZATION NOTE (sources.search.key2): Key shortcut to open the search for\n# searching all the source files the debugger has seen.\nsources.search.key2=CmdOrCtrl+P\n\n# LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the\n# search for searching all the source files the debugger has seen.\nsources.search.alt.key=CmdOrCtrl+O\n\n# LOCALIZATION NOTE (projectTextSearch.key): A key shortcut to open the\n# full project text search for searching all the files the debugger has seen.\nprojectTextSearch.key=CmdOrCtrl+Shift+F\n\n# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the\n# modal for searching functions in a file.\nfunctionSearch.key=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE (toggleBreakpoint.key): A key shortcut to toggle\n# breakpoints.\ntoggleBreakpoint.key=CmdOrCtrl+B\n\n# LOCALIZATION NOTE (toggleCondPanel.key): A key shortcut to toggle\n# the conditional breakpoint panel.\ntoggleCondPanel.key=CmdOrCtrl+Shift+B\n\n# LOCALIZATION NOTE (stepOut.key): A key shortcut to\n# step out.\nstepOut.key=Shift+F11\n\n# LOCALIZATION NOTE (shortcuts.header.editor): Sections header in\n# the shortcuts modal for keyboard shortcuts related to editing.\nshortcuts.header.editor=Editor\n\n# LOCALIZATION NOTE (shortcuts.header.stepping): Sections header in\n# the shortcuts modal for keyboard shortcuts related to stepping.\nshortcuts.header.stepping=Stepping\n\n# LOCALIZATION NOTE (shortcuts.header.search): Sections header in\n# the shortcuts modal for keyboard shortcuts related to search.\nshortcuts.header.search=Search\n\n# LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown\n# when searching across all of the files in a project.\nprojectTextSearch.placeholder=Find in files…\n\n# LOCALIZATION NOTE (projectTextSearch.noResults): The center pane Text Search\n# message when the query did not match any text of all files in a project.\nprojectTextSearch.noResults=No results found\n\n# LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger\n# does not have any sources.\nsources.noSourcesAvailable=This page has no sources\n\n# LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search\n# for searching within a the currently opened files in the editor\nsourceSearch.search.key2=CmdOrCtrl+F\n\n# LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in\n# the source search input bar\nsourceSearch.search.placeholder=Search in file…\n\n# LOCALIZATION NOTE (sourceSearch.search.again.key2): Key shortcut to highlight\n# the next occurrence of the last search triggered from a source search\nsourceSearch.search.again.key2=CmdOrCtrl+G\n\n# LOCALIZATION NOTE (sourceSearch.search.againPrev.key2): Key shortcut to highlight\n# the previous occurrence of the last search triggered from a source search\nsourceSearch.search.againPrev.key2=CmdOrCtrl+Shift+G\n\n# LOCALIZATION NOTE (sourceSearch.resultsSummary1): Shows a summary of\n# the number of matches for autocomplete\nsourceSearch.resultsSummary1=%d results\n\n# LOCALIZATION NOTE (noMatchingStringsText): The text to display in the\n# global search results when there are no matching strings after filtering.\nnoMatchingStringsText=No matches found\n\n# LOCALIZATION NOTE (emptySearchText): This is the text that appears in the\n# filter text box when it is empty and the scripts container is selected.\nemptySearchText=Search scripts (%S)\n\n# LOCALIZATION NOTE (emptyVariablesFilterText): This is the text that\n# appears in the filter text box for the variables view container.\nemptyVariablesFilterText=Filter variables\n\n# LOCALIZATION NOTE (emptyPropertiesFilterText): This is the text that\n# appears in the filter text box for the editor's variables view bubble.\nemptyPropertiesFilterText=Filter properties\n\n# LOCALIZATION NOTE (searchPanelFilter): This is the text that appears in the\n# filter panel popup for the filter scripts operation.\nsearchPanelFilter=Filter scripts (%S)\n\n# LOCALIZATION NOTE (searchPanelGlobal): This is the text that appears in the\n# filter panel popup for the global search operation.\nsearchPanelGlobal=Search in all files (%S)\n\n# LOCALIZATION NOTE (searchPanelFunction): This is the text that appears in the\n# filter panel popup for the function search operation.\nsearchPanelFunction=Search for function definition (%S)\n\n# LOCALIZATION NOTE (searchPanelToken): This is the text that appears in the\n# filter panel popup for the token search operation.\nsearchPanelToken=Find in this file (%S)\n\n# LOCALIZATION NOTE (searchPanelGoToLine): This is the text that appears in the\n# filter panel popup for the line search operation.\nsearchPanelGoToLine=Go to line (%S)\n\n# LOCALIZATION NOTE (searchPanelVariable): This is the text that appears in the\n# filter panel popup for the variables search operation.\nsearchPanelVariable=Filter variables (%S)\n\n# LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that\n# are displayed in the breakpoints menu item popup.\nbreakpointMenuItem.setConditional=Configure conditional breakpoint\nbreakpointMenuItem.enableSelf2.label=Enable\nbreakpointMenuItem.enableSelf2.accesskey=E\nbreakpointMenuItem.disableSelf2.label=Disable\nbreakpointMenuItem.disableSelf2.accesskey=D\nbreakpointMenuItem.deleteSelf2.label=Remove\nbreakpointMenuItem.deleteSelf2.accesskey=R\nbreakpointMenuItem.enableOthers2.label=Enable others\nbreakpointMenuItem.enableOthers2.accesskey=o\nbreakpointMenuItem.disableOthers2.label=Disable others\nbreakpointMenuItem.disableOthers2.accesskey=s\nbreakpointMenuItem.deleteOthers2.label=Remove others\nbreakpointMenuItem.deleteOthers2.accesskey=h\nbreakpointMenuItem.enableAll2.label=Enable all\nbreakpointMenuItem.enableAll2.accesskey=b\nbreakpointMenuItem.disableAll2.label=Disable all\nbreakpointMenuItem.disableAll2.accesskey=k\nbreakpointMenuItem.deleteAll2.label=Remove all\nbreakpointMenuItem.deleteAll2.accesskey=a\nbreakpointMenuItem.removeCondition2.label=Remove condition\nbreakpointMenuItem.removeCondition2.accesskey=c\nbreakpointMenuItem.addCondition2.label=Add condition\nbreakpointMenuItem.addCondition2.accesskey=A\nbreakpointMenuItem.editCondition2.label=Edit condition\nbreakpointMenuItem.editCondition2.accesskey=n\nbreakpointMenuItem.enableSelf=Enable breakpoint\nbreakpointMenuItem.enableSelf.accesskey=E\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.disableSelf.accesskey=D\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.deleteSelf.accesskey=R\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.enableOthers.accesskey=o\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.disableOthers.accesskey=s\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.deleteOthers.accesskey=h\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.enableAll.accesskey=b\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.disableAll.accesskey=k\nbreakpointMenuItem.deleteAll=Remove all breakpoints\nbreakpointMenuItem.deleteAll.accesskey=a\nbreakpointMenuItem.removeCondition.label=Remove breakpoint condition\nbreakpointMenuItem.removeCondition.accesskey=c\nbreakpointMenuItem.editCondition.label=Edit breakpoint condition\nbreakpointMenuItem.editCondition.accesskey=n\n\n# LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header.\nbreakpoints.header=Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.none): The text that appears when there are\n# no breakpoints present\nbreakpoints.none=No breakpoints\n\n# LOCALIZATION NOTE (breakpoints.enable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.enable=Enable breakpoints\n\n# LOCALIZATION NOTE (breakpoints.disable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.disable=Disable breakpoints\n\n# LOCALIZATION NOTE (breakpoints.removeBreakpointTooltip): The tooltip that is displayed\n# for remove breakpoint button in right sidebar\nbreakpoints.removeBreakpointTooltip=Remove breakpoint\n\n# LOCALIZATION NOTE (callStack.header): Call Stack right sidebar pane header.\ncallStack.header=Call stack\n\n# LOCALIZATION NOTE (callStack.notPaused): Call Stack right sidebar pane\n# message when not paused.\ncallStack.notPaused=Not paused\n\n# LOCALIZATION NOTE (callStack.collapse): Call Stack right sidebar pane\n# message to hide some of the frames that are shown.\ncallStack.collapse=Collapse rows\n\n# LOCALIZATION NOTE (callStack.expand): Call Stack right sidebar pane\n# message to show more of the frames.\ncallStack.expand=Expand rows\n\n# LOCALIZATION NOTE (editor.searchResults): Editor Search bar message\n# for the summarizing the selected search result. e.g. 5 of 10 results.\neditor.searchResults=%d of %d results\n\n# LOCALIZATION NOTE (sourceSearch.singleResult): Copy shown when there is one result.\neditor.singleResult=1 result\n\n# LOCALIZATION NOTE (editor.noResults): Editor Search bar message\n# for when no results found.\neditor.noResults=No results\n\n# LOCALIZATION NOTE (editor.searchResults.nextResult): Editor Search bar\n# tooltip for traversing to the Next Result\neditor.searchResults.nextResult=Next result\n\n# LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar\n# tooltip for traversing to the Previous Result\neditor.searchResults.prevResult=Previous result\n\n# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for\n# toggling search type buttons(function search, variable search)\neditor.searchTypeToggleTitle=Search for:\n\n# LOCALIZATION NOTE (editor.continueToHere.label): Editor gutter context\n# menu item for jumping to a new paused location\neditor.continueToHere.label=Continue to here\neditor.continueToHere.accesskey=H\n\n# LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item\n# for adding a breakpoint on a line.\neditor.addBreakpoint=Add breakpoint\n\n# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item\n# for disabling a breakpoint on a line.\neditor.disableBreakpoint=Disable breakpoint\neditor.disableBreakpoint.accesskey=D\n\n# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item\n# for enabling a breakpoint on a line.\neditor.enableBreakpoint=Enable breakpoint\n\n# LOCALIZATION NOTE (editor.removeBreakpoint): Editor gutter context menu item\n# for removing a breakpoint on a line.\neditor.removeBreakpoint=Remove breakpoint\n\n# LOCALIZATION NOTE (editor.editBreakpoint): Editor gutter context menu item\n# for setting a breakpoint condition on a line.\neditor.editBreakpoint=Edit breakpoint\n\n# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context\n# menu item for adding/editing a breakpoint condition on a line.\neditor.addConditionalBreakpoint=Add/Edit conditional breakpoint\neditor.addConditionalBreakpoint.accesskey=c\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for\n# input element inside ConditionalPanel component\neditor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Tooltip text for\n# close button inside ConditionalPanel component\neditor.conditionalPanel.close=Cancel edit breakpoint and close\n\n# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item\n# for navigating to a source mapped location\neditor.jumpToMappedLocation1=Jump to %S location\neditor.jumpToMappedLocation1.accesskey=m\n\n# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the\n# context menu to disable framework grouping.\nframework.disableGrouping=Disable framework grouping\nframework.disableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the\n# context menu to enable framework grouping.\nframework.enableGrouping=Enable framework grouping\nframework.enableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (generated): Source Map term for a server source location\ngenerated=Generated\n\n# LOCALIZATION NOTE (original): Source Map term for a debugger UI source location\noriginal=original\n\n# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression\n# input element\nexpressions.placeholder=Add watch expression\nexpressions.placeholder.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item\n# for closing the selected tab below the mouse.\nsourceTabs.closeTab=Close tab\nsourceTabs.closeTab.accesskey=c\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs): Editor source tab context menu item\n# for closing the other tabs.\nsourceTabs.closeOtherTabs=Close other tabs\nsourceTabs.closeOtherTabs.accesskey=o\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd): Editor source tab context menu item\n# for closing the tabs to the end (the right for LTR languages) of the selected tab.\nsourceTabs.closeTabsToEnd=Close tabs to the right\nsourceTabs.closeTabsToEnd.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs): Editor source tab context menu item\n# for closing all tabs.\nsourceTabs.closeAllTabs=Close all tabs\nsourceTabs.closeAllTabs.accesskey=a\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree): Editor source tab context menu item\n# for revealing source in tree.\nsourceTabs.revealInTree=Reveal in tree\nsourceTabs.revealInTree.accesskey=r\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item\n# for pretty printing the source.\nsourceTabs.prettyPrint=Pretty print source\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox source\nsourceFooter.blackbox.accesskey=B\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox source\nsourceFooter.unblackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated\n# with a blackboxed source\nsourceFooter.blackboxed=Blackboxed source\n\n# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated\n# with a code coverage button\nsourceFooter.codeCoverage=Code coverage\n\n# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed\n# for close tab button in source tabs.\nsourceTabs.closeTabButtonTooltip=Close tab\n\n# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.\nscopes.header=Scopes\n\n# LOCALIZATION NOTE (scopes.notAvailable): Scopes right sidebar pane message\n# for when the debugger is paused, but there isn't pause data.\nscopes.notAvailable=Scopes unavailable\n\n# LOCALIZATION NOTE (scopes.notPaused): Scopes right sidebar pane message\n# for when the debugger is not paused.\nscopes.notPaused=Not paused\n\n# LOCALIZATION NOTE (scopes.block): Refers to a block of code in\n# the scopes pane when the debugger is paused.\nscopes.block=Block\n\n# LOCALIZATION NOTE (sources.header): Sources left sidebar header\nsources.header=Sources\n\n# LOCALIZATION NOTE (outline.header): Outline left sidebar header\noutline.header=Outline\n\n# LOCALIZATION NOTE (outline.noFunctions): Outline text when there are no functions to display\noutline.noFunctions=No functions\n\n# LOCALIZATION NOTE (sources.search): Sources left sidebar prompt\n# e.g. Cmd+P to search. On a mac, we use the command unicode character.\n# On windows, it's ctrl.\nsources.search=%S to search\n\n# LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar\n# pane header.\nwatchExpressions.header=Watch expressions\n\n# LOCALIZATION NOTE (watchExpressions.refreshButton): Watch Expressions header\n# button for refreshing the expressions.\nwatchExpressions.refreshButton=Refresh\n\n# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's\n# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on\n# a mac we use the unicode character.\nwelcome.search=%S to search for sources\n\n# LOCALIZATION NOTE (welcome.findInFiles): The center pane welcome panel's\n# search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on\n# a mac we use the unicode character.\nwelcome.findInFiles=%S to find in files\n\n# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome\n# panel. %S is replaced by the keyboard shortcut to search for functions.\nwelcome.searchFunction=%S to search for functions in file\n\n# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search\n# prompt for searching for files.\nsourceSearch.search=Search sources…\n\n# LOCALIZATION NOTE (sourceSearch.noResults): The center pane Source Search\n# message when the query did not match any of the sources.\nsourceSearch.noResults2=No results found\n\n# LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip\n# when the debugger will not pause on exceptions.\nignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptions): The pause on exceptions button\n# tooltip when the debugger will pause on uncaught exceptions.\npauseOnUncaughtExceptions=Pause on uncaught exceptions. Click to pause on all exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptions): The pause on exceptions button tooltip\n# when the debugger will pause on all exceptions.\npauseOnExceptions=Pause on all exceptions. Click to ignore exceptions\n\n# LOCALIZATION NOTE (loadingText): The text that is displayed in the script\n# editor when the loading process has started but there is no file to display\n# yet.\nloadingText=Loading\\u2026\n\n# LOCALIZATION NOTE (errorLoadingText3): The text that is displayed in the debugger\n# viewer when there is an error loading a file\nerrorLoadingText3=Error loading this URI: %S\n\n# LOCALIZATION NOTE (addWatchExpressionText): The text that is displayed in the\n# watch expressions list to add a new item.\naddWatchExpressionText=Add watch expression\n\n# LOCALIZATION NOTE (addWatchExpressionButton): The button that is displayed in the\n# variables view popup.\naddWatchExpressionButton=Watch\n\n# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the\n# variables pane when there are no variables to display.\nemptyVariablesText=No variables to display\n\n# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables\n# pane as a header for each variable scope (e.g. \"Global scope, \"With scope\",\n# etc.).\nscopeLabel=%S scope\n\n# LOCALIZATION NOTE (watchExpressionsScopeLabel): The name of the watch\n# expressions scope. This text is displayed in the variables pane as a header for\n# the watch expressions scope.\nwatchExpressionsScopeLabel=Watch expressions\n\n# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text\n# is added to scopeLabel and displayed in the variables pane as a header for\n# the global scope.\nglobalScopeLabel=Global\n\n# LOCALIZATION NOTE (variablesViewErrorStacktrace): This is the text that is\n# shown before the stack trace in an error.\nvariablesViewErrorStacktrace=Stack trace:\n\n# LOCALIZATION NOTE (variablesViewMoreObjects): the text that is displayed\n# when you have an object preview that does not show all of the elements. At the end of the list\n# you see \"N more...\" in the web console output.\n# This is a semi-colon list of plural forms.\n# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals\n# #1 number of remaining items in the object\n# example: 3 more…\nvariablesViewMoreObjects=#1 more…;#1 more…\n\n# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed\n# in the variables list on an item with an editable name.\nvariablesEditableNameTooltip=Double click to edit\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in the variables list on an item with an editable value.\nvariablesEditableValueTooltip=Click to change value\n\n# LOCALIZATION NOTE (variablesCloseButtonTooltip): The text that is displayed\n# in the variables list on an item which can be removed.\nvariablesCloseButtonTooltip=Click to remove\n\n# LOCALIZATION NOTE (variablesEditButtonTooltip): The text that is displayed\n# in the variables list on a getter or setter which can be edited.\nvariablesEditButtonTooltip=Click to set value\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in a tooltip on the \"open in inspector\" button in the the variables list for a\n# DOMNode item.\nvariablesDomNodeValueTooltip=Click to select the node in the inspector\n\n# LOCALIZATION NOTE (configurable|...|Tooltip): The text that is displayed\n# in the variables list on certain variables or properties as tooltips.\n# Expanations of what these represent can be found at the following links:\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed\n# It's probably best to keep these in English.\nconfigurableTooltip=configurable\nenumerableTooltip=enumerable\nwritableTooltip=writable\nfrozenTooltip=frozen\nsealedTooltip=sealed\nextensibleTooltip=extensible\noverriddenTooltip=overridden\nWebIDLTooltip=WebIDL\n\n# LOCALIZATION NOTE (variablesSeparatorLabel): The text that is displayed\n# in the variables list as a separator between the name and value.\nvariablesSeparatorLabel=:\n\n# LOCALIZATION NOTE (watchExpressionsSeparatorLabel2): The text that is displayed\n# in the watch expressions list as a separator between the code and evaluation.\nwatchExpressionsSeparatorLabel2=\\u0020→\n\n# LOCALIZATION NOTE (functionSearchSeparatorLabel): The text that is displayed\n# in the functions search panel as a separator between function's inferred name\n# and its real name (if available).\nfunctionSearchSeparatorLabel=←\n\n# LOCALIZATION NOTE(gotoLineModal.placeholder): The placeholder\n# text displayed when the user searches for specific lines in a file\ngotoLineModal.placeholder=Go to line…\ngotoLineModal.key=CmdOrCtrl+Shift+;\n\n# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder\n# text displayed when the user searches for functions in a file\nsymbolSearch.search.functionsPlaceholder=Search functions…\n\n# LOCALIZATION NOTE(symbolSearch.search.variablesPlaceholder): The placeholder\n# text displayed when the user searches for variables in a file\nsymbolSearch.search.variablesPlaceholder=Search variables…\n\n# LOCALIZATION NOTE(symbolSearch.search.key2): The Key Shortcut for\n# searching for a function or variable\nsymbolSearch.search.key2=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.modifiersLabel): A label\n# preceding the group of modifiers\nsymbolSearch.searchModifier.modifiersLabel=Modifiers:\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.regex): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.regex=Regex\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.caseSensitive): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.caseSensitive=Case sensitive\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.wholeWord): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.wholeWord=Whole word\n\n# LOCALIZATION NOTE (resumptionOrderPanelTitle): This is the text that appears\n# as a description in the notification panel popup, when multiple debuggers are\n# open in separate tabs and the user tries to resume them in the wrong order.\n# The substitution parameter is the URL of the last paused window that must be\n# resumed first.\nresumptionOrderPanelTitle=There are one or more paused debuggers. Please resume the most-recently paused debugger first at: %S\n\nvariablesViewOptimizedOut=(optimized away)\nvariablesViewUninitialized=(uninitialized)\nvariablesViewMissingArgs=(unavailable)\n\nanonymousSourcesLabel=Anonymous sources\n\nexperimental=This is an experimental feature\n\n# LOCALIZATION NOTE (whyPaused.debuggerStatement): The text that is displayed\n# in a info block explaining how the debugger is currently paused due to a `debugger`\n# statement in the code\nwhyPaused.debuggerStatement=Paused on debugger statement\n\n# LOCALIZATION NOTE (whyPaused.breakpoint): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a breakpoint\nwhyPaused.breakpoint=Paused on breakpoint\n\n# LOCALIZATION NOTE (whyPaused.exception): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an exception\nwhyPaused.exception=Paused on exception\n\n# LOCALIZATION NOTE (whyPaused.resumeLimit): The text that is displayed\n# in a info block explaining how the debugger is currently paused while stepping\n# in or out of the stack\nwhyPaused.resumeLimit=Paused while stepping\n\n# LOCALIZATION NOTE (whyPaused.pauseOnDOMEvents): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# dom event\nwhyPaused.pauseOnDOMEvents=Paused on event listener\n\n# LOCALIZATION NOTE (whyPaused.breakpointConditionThrown): The text that is displayed\n# in an info block when evaluating a conditional breakpoint throws an error\nwhyPaused.breakpointConditionThrown=Error with conditional breakpoint\n\n# LOCALIZATION NOTE (whyPaused.xhr): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# xml http request\nwhyPaused.xhr=Paused on XMLHttpRequest\n\n# LOCALIZATION NOTE (whyPaused.promiseRejection): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# promise rejection\nwhyPaused.promiseRejection=Paused on promise rejection\n\n# LOCALIZATION NOTE (whyPaused.assert): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# assert\nwhyPaused.assert=Paused on assertion\n\n# LOCALIZATION NOTE (whyPaused.debugCommand): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# debugger statement\nwhyPaused.debugCommand=Paused on debugged function\n\n# LOCALIZATION NOTE (whyPaused.other): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an event\n# listener breakpoint set\nwhyPaused.other=Debugger paused\n\n# LOCALIZATION NOTE (ctrl): The text that is used for documenting\n# keyboard shortcuts that use the control key\nctrl=Ctrl\n\n# LOCALIZATION NOTE (anonymous): The text that is displayed when the\n# display name is null.\nanonymous=(anonymous)\n\n# LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing\n# keyboard shortcut action for toggling breakpoint\nshortcuts.toggleBreakpoint=Toggle Breakpoint\nshortcuts.toggleBreakpoint.accesskey=B\n\n# LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing\n# keyboard shortcut action for toggling conditional panel keyboard\nshortcuts.toggleCondPanel=Toggle Conditional Panel\n\n# LOCALIZATION NOTE (shortcuts.pauseOrResume): text describing\n# keyboard shortcut action for pause of resume\nshortcuts.pauseOrResume=Pause/Resume\n\n# LOCALIZATION NOTE (shortcuts.stepOver): text describing\n# keyboard shortcut action for stepping over\nshortcuts.stepOver=Step Over\n\n# LOCALIZATION NOTE (shortcuts.stepIn): text describing\n# keyboard shortcut action for stepping in\nshortcuts.stepIn=Step In\n\n# LOCALIZATION NOTE (shortcuts.stepOut): text describing\n# keyboard shortcut action for stepping out\nshortcuts.stepOut=Step Out\n\n# LOCALIZATION NOTE (shortcuts.fileSearch): text describing\n# keyboard shortcut action for source file search\nshortcuts.fileSearch=Source File Search\n\n# LOCALIZATION NOTE (shortcuts.searchAgain): text describing\n# keyboard shortcut action for searching again\nshortcuts.searchAgain=Search Again\n\n# LOCALIZATION NOTE (shortcuts.projectSearch): text describing\n# keyboard shortcut action for full project search\nshortcuts.projectSearch=Full Project Search\n\n# LOCALIZATION NOTE (shortcuts.functionSearch): text describing\n# keyboard shortcut action for function search\nshortcuts.functionSearch=Function Search\n\n# LOCALIZATION NOTE (shortcuts.buttonName): text describing\n# keyboard shortcut button text\nshortcuts.buttonName=Keyboard shortcuts\n"
+module.exports = "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n# LOCALIZATION NOTE These strings are used inside the Debugger\n# which is available from the Web Developer sub-menu -> 'Debugger'.\n# The correct localization of this file might be to keep it in\n# English, or another language commonly spoken among web developers.\n# You want to make that choice consistent across the developer tools.\n# A good criteria is the language in which you'd find the best\n# documentation on web development on the web.\n\n# LOCALIZATION NOTE (collapsePanes): This is the tooltip for the button\n# that collapses the left and right panes in the debugger UI.\ncollapsePanes=Collapse panes\n\n# LOCALIZATION NOTE (copySource): This is the text that appears in the\n# context menu to copy the selected source of file open.\ncopySource=Copy\ncopySource.accesskey=y\n\n# LOCALIZATION NOTE (copySourceUri2): This is the text that appears in the\n# context menu to copy the source URI of file open.\ncopySourceUri2=Copy source URI\ncopySourceUri2.accesskey=u\n\n# LOCALIZATION NOTE (setDirectoryRoot): This is the text that appears in the\n# context menu to set a directory as root directory\nsetDirectoryRoot.label=Set directory root\nsetDirectoryRoot.accesskey=r\n\n# LOCALIZATION NOTE (copyFunction): This is the text that appears in the\n# context menu to copy the function the user selected\ncopyFunction.label=Copy function\ncopyFunction.accesskey=F\n\n# LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the\n# context menu to copy the stack trace methods, file names and row number.\ncopyStackTrace=Copy stack trace\ncopyStackTrace.accesskey=c\n\n# LOCALIZATION NOTE (expandPanes): This is the tooltip for the button\n# that expands the left and right panes in the debugger UI.\nexpandPanes=Expand panes\n\n# LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause\n# button when the debugger is in a running state.\npauseButtonTooltip=Pause %S\n\n# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for\n# the pause button after it's been clicked but before the next JavaScript to run.\npausePendingButtonTooltip=Waiting for next execution\n\n# LOCALIZATION NOTE (resumeButtonTooltip): The label that is displayed on the pause\n# button when the debugger is in a paused state.\nresumeButtonTooltip=Resume %S\n\n# LOCALIZATION NOTE (stepOverTooltip): The label that is displayed on the\n# button that steps over a function call.\nstepOverTooltip=Step over %S\n\n# LOCALIZATION NOTE (stepInTooltip): The label that is displayed on the\n# button that steps into a function call.\nstepInTooltip=Step in %S\n\n# LOCALIZATION NOTE (stepOutTooltip): The label that is displayed on the\n# button that steps out of a function call.\nstepOutTooltip=Step out %S\n\n# LOCALIZATION NOTE (workersHeader): The text to display in the events\n# header.\nworkersHeader=Workers\n\n# LOCALIZATION NOTE (noWorkersText): The text to display in the workers list\n# when there are no workers.\nnoWorkersText=This page has no workers.\n\n# LOCALIZATION NOTE (noSourcesText): The text to display in the sources list\n# when there are no sources.\nnoSourcesText=This page has no sources.\n\n# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab\n# when there are no events.\nnoEventListenersText=No event listeners to display.\n\n# LOCALIZATION NOTE (eventListenersHeader): The text to display in the events\n# header.\neventListenersHeader=Event listeners\n\n# LOCALIZATION NOTE (noStackFramesText): The text to display in the call stack tab\n# when there are no stack frames.\nnoStackFramesText=No stack frames to display\n\n# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when\n# the user hovers over the checkbox used to toggle an event breakpoint.\neventCheckboxTooltip=Toggle breaking on this event\n\n# LOCALIZATION NOTE (eventOnSelector): The text to display in the events tab\n# for every event item, between the event type and event selector.\neventOnSelector=on\n\n# LOCALIZATION NOTE (eventInSource): The text to display in the events tab\n# for every event item, between the event selector and listener's owner source.\neventInSource=in\n\n# LOCALIZATION NOTE (eventNodes): The text to display in the events tab when\n# an event is listened on more than one target node.\neventNodes=%S nodes\n\n# LOCALIZATION NOTE (eventNative): The text to display in the events tab when\n# a listener is added from plugins, thus getting translated to native code.\neventNative=[native code]\n\n# LOCALIZATION NOTE (*Events): The text to display in the events tab for\n# each group of sub-level event entries.\nanimationEvents=Animation\naudioEvents=Audio\nbatteryEvents=Battery\nclipboardEvents=Clipboard\ncompositionEvents=Composition\ndeviceEvents=Device\ndisplayEvents=Display\ndragAndDropEvents=Drag and Drop\ngamepadEvents=Gamepad\nindexedDBEvents=IndexedDB\ninteractionEvents=Interaction\nkeyboardEvents=Keyboard\nmediaEvents=HTML5 Media\nmouseEvents=Mouse\nmutationEvents=Mutation\nnavigationEvents=Navigation\npointerLockEvents=Pointer Lock\nsensorEvents=Sensor\nstorageEvents=Storage\ntimeEvents=Time\ntouchEvents=Touch\notherEvents=Other\n\n# LOCALIZATION NOTE (blackboxCheckboxTooltip2): The tooltip text to display when\n# the user hovers over the checkbox used to toggle blackboxing its associated\n# source.\nblackboxCheckboxTooltip2=Toggle blackboxing\n\n# LOCALIZATION NOTE (sources.search.key2): Key shortcut to open the search for\n# searching all the source files the debugger has seen.\nsources.search.key2=CmdOrCtrl+P\n\n# LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the\n# search for searching all the source files the debugger has seen.\nsources.search.alt.key=CmdOrCtrl+O\n\n# LOCALIZATION NOTE (projectTextSearch.key): A key shortcut to open the\n# full project text search for searching all the files the debugger has seen.\nprojectTextSearch.key=CmdOrCtrl+Shift+F\n\n# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the\n# modal for searching functions in a file.\nfunctionSearch.key=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE (toggleBreakpoint.key): A key shortcut to toggle\n# breakpoints.\ntoggleBreakpoint.key=CmdOrCtrl+B\n\n# LOCALIZATION NOTE (toggleCondPanel.key): A key shortcut to toggle\n# the conditional breakpoint panel.\ntoggleCondPanel.key=CmdOrCtrl+Shift+B\n\n# LOCALIZATION NOTE (stepOut.key): A key shortcut to\n# step out.\nstepOut.key=Shift+F11\n\n# LOCALIZATION NOTE (shortcuts.header.editor): Sections header in\n# the shortcuts modal for keyboard shortcuts related to editing.\nshortcuts.header.editor=Editor\n\n# LOCALIZATION NOTE (shortcuts.header.stepping): Sections header in\n# the shortcuts modal for keyboard shortcuts related to stepping.\nshortcuts.header.stepping=Stepping\n\n# LOCALIZATION NOTE (shortcuts.header.search): Sections header in\n# the shortcuts modal for keyboard shortcuts related to search.\nshortcuts.header.search=Search\n\n# LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown\n# when searching across all of the files in a project.\nprojectTextSearch.placeholder=Find in files…\n\n# LOCALIZATION NOTE (projectTextSearch.noResults): The center pane Text Search\n# message when the query did not match any text of all files in a project.\nprojectTextSearch.noResults=No results found\n\n# LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger\n# does not have any sources.\nsources.noSourcesAvailable=This page has no sources\n\n# LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search\n# for searching within a the currently opened files in the editor\nsourceSearch.search.key2=CmdOrCtrl+F\n\n# LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in\n# the source search input bar\nsourceSearch.search.placeholder=Search in file…\n\n# LOCALIZATION NOTE (sourceSearch.search.again.key2): Key shortcut to highlight\n# the next occurrence of the last search triggered from a source search\nsourceSearch.search.again.key2=CmdOrCtrl+G\n\n# LOCALIZATION NOTE (sourceSearch.search.againPrev.key2): Key shortcut to highlight\n# the previous occurrence of the last search triggered from a source search\nsourceSearch.search.againPrev.key2=CmdOrCtrl+Shift+G\n\n# LOCALIZATION NOTE (sourceSearch.resultsSummary1): Shows a summary of\n# the number of matches for autocomplete\nsourceSearch.resultsSummary1=%d results\n\n# LOCALIZATION NOTE (noMatchingStringsText): The text to display in the\n# global search results when there are no matching strings after filtering.\nnoMatchingStringsText=No matches found\n\n# LOCALIZATION NOTE (emptySearchText): This is the text that appears in the\n# filter text box when it is empty and the scripts container is selected.\nemptySearchText=Search scripts (%S)\n\n# LOCALIZATION NOTE (emptyVariablesFilterText): This is the text that\n# appears in the filter text box for the variables view container.\nemptyVariablesFilterText=Filter variables\n\n# LOCALIZATION NOTE (emptyPropertiesFilterText): This is the text that\n# appears in the filter text box for the editor's variables view bubble.\nemptyPropertiesFilterText=Filter properties\n\n# LOCALIZATION NOTE (searchPanelFilter): This is the text that appears in the\n# filter panel popup for the filter scripts operation.\nsearchPanelFilter=Filter scripts (%S)\n\n# LOCALIZATION NOTE (searchPanelGlobal): This is the text that appears in the\n# filter panel popup for the global search operation.\nsearchPanelGlobal=Search in all files (%S)\n\n# LOCALIZATION NOTE (searchPanelFunction): This is the text that appears in the\n# filter panel popup for the function search operation.\nsearchPanelFunction=Search for function definition (%S)\n\n# LOCALIZATION NOTE (searchPanelToken): This is the text that appears in the\n# filter panel popup for the token search operation.\nsearchPanelToken=Find in this file (%S)\n\n# LOCALIZATION NOTE (searchPanelGoToLine): This is the text that appears in the\n# filter panel popup for the line search operation.\nsearchPanelGoToLine=Go to line (%S)\n\n# LOCALIZATION NOTE (searchPanelVariable): This is the text that appears in the\n# filter panel popup for the variables search operation.\nsearchPanelVariable=Filter variables (%S)\n\n# LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that\n# are displayed in the breakpoints menu item popup.\nbreakpointMenuItem.setConditional=Configure conditional breakpoint\nbreakpointMenuItem.enableSelf2.label=Enable\nbreakpointMenuItem.enableSelf2.accesskey=E\nbreakpointMenuItem.disableSelf2.label=Disable\nbreakpointMenuItem.disableSelf2.accesskey=D\nbreakpointMenuItem.deleteSelf2.label=Remove\nbreakpointMenuItem.deleteSelf2.accesskey=R\nbreakpointMenuItem.enableOthers2.label=Enable others\nbreakpointMenuItem.enableOthers2.accesskey=o\nbreakpointMenuItem.disableOthers2.label=Disable others\nbreakpointMenuItem.disableOthers2.accesskey=s\nbreakpointMenuItem.deleteOthers2.label=Remove others\nbreakpointMenuItem.deleteOthers2.accesskey=h\nbreakpointMenuItem.enableAll2.label=Enable all\nbreakpointMenuItem.enableAll2.accesskey=b\nbreakpointMenuItem.disableAll2.label=Disable all\nbreakpointMenuItem.disableAll2.accesskey=k\nbreakpointMenuItem.deleteAll2.label=Remove all\nbreakpointMenuItem.deleteAll2.accesskey=a\nbreakpointMenuItem.removeCondition2.label=Remove condition\nbreakpointMenuItem.removeCondition2.accesskey=c\nbreakpointMenuItem.addCondition2.label=Add condition\nbreakpointMenuItem.addCondition2.accesskey=A\nbreakpointMenuItem.editCondition2.label=Edit condition\nbreakpointMenuItem.editCondition2.accesskey=n\nbreakpointMenuItem.enableSelf=Enable breakpoint\nbreakpointMenuItem.enableSelf.accesskey=E\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.disableSelf.accesskey=D\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.deleteSelf.accesskey=R\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.enableOthers.accesskey=o\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.disableOthers.accesskey=s\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.deleteOthers.accesskey=h\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.enableAll.accesskey=b\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.disableAll.accesskey=k\nbreakpointMenuItem.deleteAll=Remove all breakpoints\nbreakpointMenuItem.deleteAll.accesskey=a\nbreakpointMenuItem.removeCondition.label=Remove breakpoint condition\nbreakpointMenuItem.removeCondition.accesskey=c\nbreakpointMenuItem.editCondition.label=Edit breakpoint condition\nbreakpointMenuItem.editCondition.accesskey=n\n\n# LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header.\nbreakpoints.header=Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.none): The text that appears when there are\n# no breakpoints present\nbreakpoints.none=No breakpoints\n\n# LOCALIZATION NOTE (breakpoints.enable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.enable=Enable breakpoints\n\n# LOCALIZATION NOTE (breakpoints.disable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.disable=Disable breakpoints\n\n# LOCALIZATION NOTE (breakpoints.removeBreakpointTooltip): The tooltip that is displayed\n# for remove breakpoint button in right sidebar\nbreakpoints.removeBreakpointTooltip=Remove breakpoint\n\n# LOCALIZATION NOTE (callStack.header): Call Stack right sidebar pane header.\ncallStack.header=Call stack\n\n# LOCALIZATION NOTE (callStack.notPaused): Call Stack right sidebar pane\n# message when not paused.\ncallStack.notPaused=Not paused\n\n# LOCALIZATION NOTE (callStack.collapse): Call Stack right sidebar pane\n# message to hide some of the frames that are shown.\ncallStack.collapse=Collapse rows\n\n# LOCALIZATION NOTE (callStack.expand): Call Stack right sidebar pane\n# message to show more of the frames.\ncallStack.expand=Expand rows\n\n# LOCALIZATION NOTE (editor.searchResults): Editor Search bar message\n# for the summarizing the selected search result. e.g. 5 of 10 results.\neditor.searchResults=%d of %d results\n\n# LOCALIZATION NOTE (sourceSearch.singleResult): Copy shown when there is one result.\neditor.singleResult=1 result\n\n# LOCALIZATION NOTE (editor.noResults): Editor Search bar message\n# for when no results found.\neditor.noResults=No results\n\n# LOCALIZATION NOTE (editor.searchResults.nextResult): Editor Search bar\n# tooltip for traversing to the Next Result\neditor.searchResults.nextResult=Next result\n\n# LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar\n# tooltip for traversing to the Previous Result\neditor.searchResults.prevResult=Previous result\n\n# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for\n# toggling search type buttons(function search, variable search)\neditor.searchTypeToggleTitle=Search for:\n\n# LOCALIZATION NOTE (editor.continueToHere.label): Editor gutter context\n# menu item for jumping to a new paused location\neditor.continueToHere.label=Continue to here\neditor.continueToHere.accesskey=H\n\n# LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item\n# for adding a breakpoint on a line.\neditor.addBreakpoint=Add breakpoint\n\n# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item\n# for disabling a breakpoint on a line.\neditor.disableBreakpoint=Disable breakpoint\neditor.disableBreakpoint.accesskey=D\n\n# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item\n# for enabling a breakpoint on a line.\neditor.enableBreakpoint=Enable breakpoint\n\n# LOCALIZATION NOTE (editor.removeBreakpoint): Editor gutter context menu item\n# for removing a breakpoint on a line.\neditor.removeBreakpoint=Remove breakpoint\n\n# LOCALIZATION NOTE (editor.editBreakpoint): Editor gutter context menu item\n# for setting a breakpoint condition on a line.\neditor.editBreakpoint=Edit breakpoint\n\n# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context\n# menu item for adding a breakpoint condition on a line.\neditor.addConditionalBreakpoint=Add conditional breakpoint\neditor.addConditionalBreakpoint.accesskey=c\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for\n# input element inside ConditionalPanel component\neditor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Tooltip text for\n# close button inside ConditionalPanel component\neditor.conditionalPanel.close=Cancel edit breakpoint and close\n\n# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item\n# for navigating to a source mapped location\neditor.jumpToMappedLocation1=Jump to %S location\neditor.jumpToMappedLocation1.accesskey=m\n\n# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the\n# context menu to disable framework grouping.\nframework.disableGrouping=Disable framework grouping\nframework.disableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the\n# context menu to enable framework grouping.\nframework.enableGrouping=Enable framework grouping\nframework.enableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (generated): Source Map term for a server source location\ngenerated=Generated\n\n# LOCALIZATION NOTE (original): Source Map term for a debugger UI source location\noriginal=original\n\n# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression\n# input element\nexpressions.placeholder=Add watch expression\nexpressions.label=Add watch expression\nexpressions.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item\n# for closing the selected tab below the mouse.\nsourceTabs.closeTab=Close tab\nsourceTabs.closeTab.accesskey=c\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs): Editor source tab context menu item\n# for closing the other tabs.\nsourceTabs.closeOtherTabs=Close other tabs\nsourceTabs.closeOtherTabs.accesskey=o\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd): Editor source tab context menu item\n# for closing the tabs to the end (the right for LTR languages) of the selected tab.\nsourceTabs.closeTabsToEnd=Close tabs to the right\nsourceTabs.closeTabsToEnd.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs): Editor source tab context menu item\n# for closing all tabs.\nsourceTabs.closeAllTabs=Close all tabs\nsourceTabs.closeAllTabs.accesskey=a\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree): Editor source tab context menu item\n# for revealing source in tree.\nsourceTabs.revealInTree=Reveal in tree\nsourceTabs.revealInTree.accesskey=r\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item\n# for pretty printing the source.\nsourceTabs.prettyPrint=Pretty print source\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox source\nsourceFooter.blackbox.accesskey=B\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox source\nsourceFooter.unblackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated\n# with a blackboxed source\nsourceFooter.blackboxed=Blackboxed source\n\n# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated\n# with a code coverage button\nsourceFooter.codeCoverage=Code coverage\n\n# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed\n# for close tab button in source tabs.\nsourceTabs.closeTabButtonTooltip=Close tab\n\n# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.\nscopes.header=Scopes\n\n# LOCALIZATION NOTE (scopes.notAvailable): Scopes right sidebar pane message\n# for when the debugger is paused, but there isn't pause data.\nscopes.notAvailable=Scopes unavailable\n\n# LOCALIZATION NOTE (scopes.notPaused): Scopes right sidebar pane message\n# for when the debugger is not paused.\nscopes.notPaused=Not paused\n\n# LOCALIZATION NOTE (scopes.block): Refers to a block of code in\n# the scopes pane when the debugger is paused.\nscopes.block=Block\n\n# LOCALIZATION NOTE (sources.header): Sources left sidebar header\nsources.header=Sources\n\n# LOCALIZATION NOTE (outline.header): Outline left sidebar header\noutline.header=Outline\n\n# LOCALIZATION NOTE (outline.noFunctions): Outline text when there are no functions to display\noutline.noFunctions=No functions\n\n# LOCALIZATION NOTE (sources.search): Sources left sidebar prompt\n# e.g. Cmd+P to search. On a mac, we use the command unicode character.\n# On windows, it's ctrl.\nsources.search=%S to search\n\n# LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar\n# pane header.\nwatchExpressions.header=Watch expressions\n\n# LOCALIZATION NOTE (watchExpressions.refreshButton): Watch Expressions header\n# button for refreshing the expressions.\nwatchExpressions.refreshButton=Refresh\n\n# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's\n# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on\n# a mac we use the unicode character.\nwelcome.search=%S to search for sources\n\n# LOCALIZATION NOTE (welcome.findInFiles): The center pane welcome panel's\n# search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on\n# a mac we use the unicode character.\nwelcome.findInFiles=%S to find in files\n\n# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome\n# panel. %S is replaced by the keyboard shortcut to search for functions.\nwelcome.searchFunction=%S to search for functions in file\n\n# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search\n# prompt for searching for files.\nsourceSearch.search=Search sources…\n\n# LOCALIZATION NOTE (sourceSearch.noResults): The center pane Source Search\n# message when the query did not match any of the sources.\nsourceSearch.noResults2=No results found\n\n# LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip\n# when the debugger will not pause on exceptions.\nignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptions): The pause on exceptions button\n# tooltip when the debugger will pause on uncaught exceptions.\npauseOnUncaughtExceptions=Pause on uncaught exceptions. Click to pause on all exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptions): The pause on exceptions button tooltip\n# when the debugger will pause on all exceptions.\npauseOnExceptions=Pause on all exceptions. Click to ignore exceptions\n\n# LOCALIZATION NOTE (loadingText): The text that is displayed in the script\n# editor when the loading process has started but there is no file to display\n# yet.\nloadingText=Loading\\u2026\n\n# LOCALIZATION NOTE (errorLoadingText3): The text that is displayed in the debugger\n# viewer when there is an error loading a file\nerrorLoadingText3=Error loading this URI: %S\n\n# LOCALIZATION NOTE (addWatchExpressionText): The text that is displayed in the\n# watch expressions list to add a new item.\naddWatchExpressionText=Add watch expression\n\n# LOCALIZATION NOTE (addWatchExpressionButton): The button that is displayed in the\n# variables view popup.\naddWatchExpressionButton=Watch\n\n# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the\n# variables pane when there are no variables to display.\nemptyVariablesText=No variables to display\n\n# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables\n# pane as a header for each variable scope (e.g. \"Global scope, \"With scope\",\n# etc.).\nscopeLabel=%S scope\n\n# LOCALIZATION NOTE (watchExpressionsScopeLabel): The name of the watch\n# expressions scope. This text is displayed in the variables pane as a header for\n# the watch expressions scope.\nwatchExpressionsScopeLabel=Watch expressions\n\n# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text\n# is added to scopeLabel and displayed in the variables pane as a header for\n# the global scope.\nglobalScopeLabel=Global\n\n# LOCALIZATION NOTE (variablesViewErrorStacktrace): This is the text that is\n# shown before the stack trace in an error.\nvariablesViewErrorStacktrace=Stack trace:\n\n# LOCALIZATION NOTE (variablesViewMoreObjects): the text that is displayed\n# when you have an object preview that does not show all of the elements. At the end of the list\n# you see \"N more...\" in the web console output.\n# This is a semi-colon list of plural forms.\n# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals\n# #1 number of remaining items in the object\n# example: 3 more…\nvariablesViewMoreObjects=#1 more…;#1 more…\n\n# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed\n# in the variables list on an item with an editable name.\nvariablesEditableNameTooltip=Double click to edit\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in the variables list on an item with an editable value.\nvariablesEditableValueTooltip=Click to change value\n\n# LOCALIZATION NOTE (variablesCloseButtonTooltip): The text that is displayed\n# in the variables list on an item which can be removed.\nvariablesCloseButtonTooltip=Click to remove\n\n# LOCALIZATION NOTE (variablesEditButtonTooltip): The text that is displayed\n# in the variables list on a getter or setter which can be edited.\nvariablesEditButtonTooltip=Click to set value\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in a tooltip on the \"open in inspector\" button in the the variables list for a\n# DOMNode item.\nvariablesDomNodeValueTooltip=Click to select the node in the inspector\n\n# LOCALIZATION NOTE (configurable|...|Tooltip): The text that is displayed\n# in the variables list on certain variables or properties as tooltips.\n# Expanations of what these represent can be found at the following links:\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed\n# It's probably best to keep these in English.\nconfigurableTooltip=configurable\nenumerableTooltip=enumerable\nwritableTooltip=writable\nfrozenTooltip=frozen\nsealedTooltip=sealed\nextensibleTooltip=extensible\noverriddenTooltip=overridden\nWebIDLTooltip=WebIDL\n\n# LOCALIZATION NOTE (variablesSeparatorLabel): The text that is displayed\n# in the variables list as a separator between the name and value.\nvariablesSeparatorLabel=:\n\n# LOCALIZATION NOTE (watchExpressionsSeparatorLabel2): The text that is displayed\n# in the watch expressions list as a separator between the code and evaluation.\nwatchExpressionsSeparatorLabel2=\\u0020→\n\n# LOCALIZATION NOTE (functionSearchSeparatorLabel): The text that is displayed\n# in the functions search panel as a separator between function's inferred name\n# and its real name (if available).\nfunctionSearchSeparatorLabel=←\n\n# LOCALIZATION NOTE(gotoLineModal.placeholder): The placeholder\n# text displayed when the user searches for specific lines in a file\ngotoLineModal.placeholder=Go to line…\ngotoLineModal.key=CmdOrCtrl+Shift+;\n\n# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder\n# text displayed when the user searches for functions in a file\nsymbolSearch.search.functionsPlaceholder=Search functions…\n\n# LOCALIZATION NOTE(symbolSearch.search.variablesPlaceholder): The placeholder\n# text displayed when the user searches for variables in a file\nsymbolSearch.search.variablesPlaceholder=Search variables…\n\n# LOCALIZATION NOTE(symbolSearch.search.key2): The Key Shortcut for\n# searching for a function or variable\nsymbolSearch.search.key2=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.modifiersLabel): A label\n# preceding the group of modifiers\nsymbolSearch.searchModifier.modifiersLabel=Modifiers:\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.regex): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.regex=Regex\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.caseSensitive): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.caseSensitive=Case sensitive\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.wholeWord): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.wholeWord=Whole word\n\n# LOCALIZATION NOTE (resumptionOrderPanelTitle): This is the text that appears\n# as a description in the notification panel popup, when multiple debuggers are\n# open in separate tabs and the user tries to resume them in the wrong order.\n# The substitution parameter is the URL of the last paused window that must be\n# resumed first.\nresumptionOrderPanelTitle=There are one or more paused debuggers. Please resume the most-recently paused debugger first at: %S\n\nvariablesViewOptimizedOut=(optimized away)\nvariablesViewUninitialized=(uninitialized)\nvariablesViewMissingArgs=(unavailable)\n\nanonymousSourcesLabel=Anonymous sources\n\nexperimental=This is an experimental feature\n\n# LOCALIZATION NOTE (whyPaused.debuggerStatement): The text that is displayed\n# in a info block explaining how the debugger is currently paused due to a `debugger`\n# statement in the code\nwhyPaused.debuggerStatement=Paused on debugger statement\n\n# LOCALIZATION NOTE (whyPaused.breakpoint): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a breakpoint\nwhyPaused.breakpoint=Paused on breakpoint\n\n# LOCALIZATION NOTE (whyPaused.exception): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an exception\nwhyPaused.exception=Paused on exception\n\n# LOCALIZATION NOTE (whyPaused.resumeLimit): The text that is displayed\n# in a info block explaining how the debugger is currently paused while stepping\n# in or out of the stack\nwhyPaused.resumeLimit=Paused while stepping\n\n# LOCALIZATION NOTE (whyPaused.pauseOnDOMEvents): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# dom event\nwhyPaused.pauseOnDOMEvents=Paused on event listener\n\n# LOCALIZATION NOTE (whyPaused.breakpointConditionThrown): The text that is displayed\n# in an info block when evaluating a conditional breakpoint throws an error\nwhyPaused.breakpointConditionThrown=Error with conditional breakpoint\n\n# LOCALIZATION NOTE (whyPaused.xhr): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# xml http request\nwhyPaused.xhr=Paused on XMLHttpRequest\n\n# LOCALIZATION NOTE (whyPaused.promiseRejection): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# promise rejection\nwhyPaused.promiseRejection=Paused on promise rejection\n\n# LOCALIZATION NOTE (whyPaused.assert): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# assert\nwhyPaused.assert=Paused on assertion\n\n# LOCALIZATION NOTE (whyPaused.debugCommand): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# debugger statement\nwhyPaused.debugCommand=Paused on debugged function\n\n# LOCALIZATION NOTE (whyPaused.other): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an event\n# listener breakpoint set\nwhyPaused.other=Debugger paused\n\n# LOCALIZATION NOTE (ctrl): The text that is used for documenting\n# keyboard shortcuts that use the control key\nctrl=Ctrl\n\n# LOCALIZATION NOTE (anonymous): The text that is displayed when the\n# display name is null.\nanonymous=(anonymous)\n\n# LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing\n# keyboard shortcut action for toggling breakpoint\nshortcuts.toggleBreakpoint=Toggle Breakpoint\nshortcuts.toggleBreakpoint.accesskey=B\n\n# LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing\n# keyboard shortcut action for toggling conditional panel keyboard\nshortcuts.toggleCondPanel=Toggle Conditional Panel\n\n# LOCALIZATION NOTE (shortcuts.pauseOrResume): text describing\n# keyboard shortcut action for pause of resume\nshortcuts.pauseOrResume=Pause/Resume\n\n# LOCALIZATION NOTE (shortcuts.stepOver): text describing\n# keyboard shortcut action for stepping over\nshortcuts.stepOver=Step Over\n\n# LOCALIZATION NOTE (shortcuts.stepIn): text describing\n# keyboard shortcut action for stepping in\nshortcuts.stepIn=Step In\n\n# LOCALIZATION NOTE (shortcuts.stepOut): text describing\n# keyboard shortcut action for stepping out\nshortcuts.stepOut=Step Out\n\n# LOCALIZATION NOTE (shortcuts.fileSearch): text describing\n# keyboard shortcut action for source file search\nshortcuts.fileSearch=Source File Search\n\n# LOCALIZATION NOTE (shortcuts.searchAgain): text describing\n# keyboard shortcut action for searching again\nshortcuts.searchAgain=Search Again\n\n# LOCALIZATION NOTE (shortcuts.projectSearch): text describing\n# keyboard shortcut action for full project search\nshortcuts.projectSearch=Full Project Search\n\n# LOCALIZATION NOTE (shortcuts.functionSearch): text describing\n# keyboard shortcut action for function search\nshortcuts.functionSearch=Function Search\n\n# LOCALIZATION NOTE (shortcuts.buttonName): text describing\n# keyboard shortcut button text\nshortcuts.buttonName=Keyboard shortcuts\n"
 
 /***/ }),
 /* 961 */,
 /* 962 */,
 /* 963 */,
 /* 964 */,
 /* 965 */
 /***/ (function(module, exports) {
@@ -16186,22 +16186,17 @@ module.exports = "<svg version=\"1.1\" x
 
 /***/ }),
 /* 1296 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
 /***/ }),
-/* 1297 */
-/***/ (function(module, exports) {
-
-// removed by extract-text-webpack-plugin
-
-/***/ }),
+/* 1297 */,
 /* 1298 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
 /***/ }),
 /* 1299 */
 /***/ (function(module, exports) {
@@ -16294,22 +16289,17 @@ module.exports = "<svg version=\"1.1\" x
 
 /***/ }),
 /* 1314 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
 /***/ }),
-/* 1315 */
-/***/ (function(module, exports) {
-
-// removed by extract-text-webpack-plugin
-
-/***/ }),
+/* 1315 */,
 /* 1316 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
 /***/ }),
 /* 1317 */
 /***/ (function(module, exports) {
@@ -16552,19 +16542,19 @@ var ast = _interopRequireWildcard(_ast);
 var _coverage = __webpack_require__(1423);
 
 var coverage = _interopRequireWildcard(_coverage);
 
 var _projectTextSearch = __webpack_require__(1424);
 
 var projectTextSearch = _interopRequireWildcard(_projectTextSearch);
 
-var _sourceSearch = __webpack_require__(1425);
-
-var sourceSearch = _interopRequireWildcard(_sourceSearch);
+var _quickOpen = __webpack_require__(1635);
+
+var quickOpen = _interopRequireWildcard(_quickOpen);
 
 var _sourceTree = __webpack_require__(1426);
 
 var sourceTree = _interopRequireWildcard(_sourceTree);
 
 var _breakpointAtLocation = __webpack_require__(1503);
 
 var _breakpointAtLocation2 = _interopRequireDefault(_breakpointAtLocation);
@@ -16584,17 +16574,17 @@ var _isSelectedFrameVisible2 = _interopR
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
 
 /**
  * @param object - location
  */
 
-module.exports = _extends({}, expressions, sources, pause, debuggee, breakpoints, pendingBreakpoints, eventListeners, ui, ast, coverage, fileSearch, projectTextSearch, sourceSearch, sourceTree, {
+module.exports = _extends({}, expressions, sources, pause, debuggee, breakpoints, pendingBreakpoints, eventListeners, ui, ast, coverage, fileSearch, projectTextSearch, quickOpen, sourceTree, {
   getBreakpointAtLocation: _breakpointAtLocation2.default,
   getInScopeLines: _linesInScope2.default,
   getVisibleBreakpoints: _visibleBreakpoints2.default,
   isSelectedFrameVisible: _isSelectedFrameVisible2.default
 });
 
 /***/ }),
 /* 1353 */
@@ -17031,17 +17021,17 @@ var expressions = _interopRequireWildcar
 var _eventListeners = __webpack_require__(1527);
 
 var eventListeners = _interopRequireWildcard(_eventListeners);
 
 var _sources = __webpack_require__(1373);
 
 var sources = _interopRequireWildcard(_sources);
 
-var _pause = __webpack_require__(1528);
+var _pause = __webpack_require__(1639);
 
 var pause = _interopRequireWildcard(_pause);
 
 var _navigation = __webpack_require__(1529);
 
 var navigation = _interopRequireWildcard(_navigation);
 
 var _ui = __webpack_require__(1385);
@@ -17059,19 +17049,19 @@ var ast = _interopRequireWildcard(_ast);
 var _coverage = __webpack_require__(1531);
 
 var coverage = _interopRequireWildcard(_coverage);
 
 var _projectTextSearch = __webpack_require__(1433);
 
 var projectTextSearch = _interopRequireWildcard(_projectTextSearch);
 
-var _sourceSearch = __webpack_require__(1434);
-
-var sourceSearch = _interopRequireWildcard(_sourceSearch);
+var _quickOpen = __webpack_require__(1647);
+
+var quickOpen = _interopRequireWildcard(_quickOpen);
 
 var _sourceTree = __webpack_require__(1532);
 
 var sourceTree = _interopRequireWildcard(_sourceTree);
 
 var _loadSourceText = __webpack_require__(1435);
 
 var loadSourceText = _interopRequireWildcard(_loadSourceText);
@@ -17081,17 +17071,17 @@ var _debuggee = __webpack_require__(1533
 var debuggee = _interopRequireWildcard(_debuggee);
 
 var _toolbox = __webpack_require__(1534);
 
 var toolbox = _interopRequireWildcard(_toolbox);
 
 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
 
-exports.default = Object.assign({}, navigation, breakpoints, expressions, eventListeners, sources, pause, ui, fileSearch, ast, coverage, projectTextSearch, sourceSearch, sourceTree, loadSourceText, debuggee, toolbox);
+exports.default = Object.assign({}, navigation, breakpoints, expressions, eventListeners, sources, pause, ui, fileSearch, ast, coverage, projectTextSearch, quickOpen, sourceTree, loadSourceText, debuggee, toolbox);
 
 /***/ }),
 /* 1355 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
@@ -17487,16 +17477,25 @@ function toEditorRange(sourceId, locatio
     end: toEditorPosition(sourceId, end)
   };
 }
 
 function toSourceLine(sourceId, line) {
   return (0, _wasm.isWasm)(sourceId) ? (0, _wasm.lineToWasmOffset)(sourceId, line) : line + 1;
 }
 
+function scrollToColumn(codeMirror, line, column) {
+  const { top, left } = codeMirror.charCoords({ line: line, ch: column }, "local");
+
+  const centeredX = left - codeMirror.getScrollerElement().offsetWidth / 2;
+  const centeredY = top - codeMirror.getScrollerElement().offsetHeight / 2;
+
+  codeMirror.scrollTo(centeredX, centeredY);
+}
+
 function toSourceLocation(sourceId, location) {
   return {
     line: toSourceLine(sourceId, location.line),
     column: (0, _wasm.isWasm)(sourceId) ? undefined : location.column
   };
 }
 
 function markText(editor, className, location) {
@@ -17525,16 +17524,17 @@ function getSourceLocationFromMouseEvent
 
 module.exports = Object.assign({}, expressionUtils, sourceDocumentUtils, sourceSearchUtils, _devtoolsSourceEditor.SourceEditorUtils, {
   createEditor,
   isWasm: _wasm.isWasm,
   toEditorLine,
   toEditorPosition,
   toEditorRange,
   toSourceLine,
+  scrollToColumn,
   toSourceLocation,
   shouldShowPrettyPrint,
   shouldShowFooter,
   traverseResults,
   markText,
   lineAtHeight,
   getSourceLocationFromMouseEvent
 });
@@ -17703,16 +17703,30 @@ function updateTheme(className) {
     root.className = "";
     appRoot.className = className;
 
     root.classList.add(`theme-${theme}`);
     appRoot.classList.add(`theme-${theme}`);
   }
 }
 
+function updatePlatform(className) {
+  if (false) {
+    const root = document.body.parentNode;
+    const appRoot = document.querySelector(".launchpad-root");
+
+    const agent = navigator.userAgent.toLowerCase();
+    const win = agent.indexOf("windows") > -1 ? "win" : "linux";
+    const platform = agent.indexOf("mac os") > -1 ? "mac" : win;
+
+    root.classList.add("html");
+    appRoot.setAttribute("platform", platform);
+  }
+}
+
 function updateDir() {
   const dir = getValue("dir");
   const root = document.body.parentNode;
   root.dir = dir;
 }
 
 async function updateConfig() {
   const response = await fetch("/getconfig", {
@@ -17761,16 +17775,17 @@ function renderRoot(_React, _ReactDOM, c
 
   const className = "launchpad-root theme-body";
   const root = Root(className);
   mount.appendChild(root);
 
   if (isDevelopment()) {
     updateConfig();
     updateTheme(className);
+    updatePlatform();
   }
 
   if (component.props || component.propTypes) {
     _ReactDOM.render(createElement(Provider, { store: _store }, createElement(component, props)), root);
   } else {
     root.appendChild(component);
   }
 }
@@ -18182,20 +18197,16 @@ function _asyncToGenerator(fn) { return 
 
 function WorkerDispatcher() {
   this.msgId = 1;
   this.worker = null;
 } /* This Source Code Form is subject to the terms of the Mozilla Public
    * License, v. 2.0. If a copy of the MPL was not distributed with this
    * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-const mark = typeof window == "object" && window.performance && window.performance.mark ? window.performance.mark.bind(window.performance) : () => {};
-
-const measure = typeof window == "object" && window.performance && window.performance.measure ? window.performance.measure.bind(window.performance) : () => {};
-
 WorkerDispatcher.prototype = {
   start(url) {
     this.worker = new Worker(url);
     this.worker.onerror = () => {
       console.error(`Error in worker ${url}`);
     };
   },
 
@@ -18207,35 +18218,28 @@ WorkerDispatcher.prototype = {
     this.worker.terminate();
     this.worker = null;
   },
 
   task(method) {
     return (...args) => {
       return new Promise((resolve, reject) => {
         const id = this.msgId++;
-
-        mark(`${method}_start`);
-
         this.worker.postMessage({ id, method, args });
 
         const listener = ({ data: result }) => {
           if (result.id !== id) {
             return;
           }
 
           if (!this.worker) {
             reject("Oops, The worker has shutdown!");
             return;
           }
           this.worker.removeEventListener("message", listener);
-
-          mark(`${method}_end`);
-          measure(`${method}`, `${method}_start`, `${method}_end`);
-
           if (result.error) {
             reject(result.error);
           } else {
             resolve(result.response);
           }
         };
 
         this.worker.addEventListener("message", listener);
@@ -18329,16 +18333,27 @@ module.exports = {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.getSelectedSourceText = exports.getSelectedSource = exports.getSelectedLocation = exports.getSourcesForTabs = exports.getSearchTabs = exports.getSourceTabs = exports.getSources = undefined;
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+/* 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/. */
+
+/**
+ * Sources reducer
+ * @module reducers/sources
+ */
+
 exports.initialState = initialState;
 exports.removeSourceFromTabList = removeSourceFromTabList;
 exports.removeSourcesFromTabList = removeSourcesFromTabList;
 exports.getNewSelectedSourceId = getNewSelectedSourceId;
 exports.getSource = getSource;
 exports.getSourceByURL = getSourceByURL;
 exports.getPendingSelectedLocation = getPendingSelectedLocation;
 exports.getPrettySource = getPrettySource;
@@ -18366,24 +18381,16 @@ function initialState() {
   return (0, _makeRecord2.default)({
     sources: I.Map(),
     selectedLocation: undefined,
     pendingSelectedLocation: _prefs.prefs.pendingSelectedLocation,
     sourcesText: I.Map(),
     tabs: I.List(restoreTabs())
   })();
 }
-/* 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/. */
-
-/**
- * Sources reducer
- * @module reducers/sources
- */
 
 function update(state = initialState(), action) {
   let location = null;
 
   switch (action.type) {
     case "ADD_SOURCE":
       {
         const source = action.source;
@@ -18399,26 +18406,24 @@ function update(state = initialState(), 
         return state;
       }
 
     case "SELECT_SOURCE":
       if (action.status != "start") {
         return state;
       }
 
-      location = {
-        line: action.line,
+      location = _extends({}, action.location, {
         url: action.source.url
-      };
+      });
 
       _prefs.prefs.pendingSelectedLocation = location;
-      return state.set("selectedLocation", {
-        sourceId: action.source.id,
-        line: action.line
-      }).set("pendingSelectedLocation", location);
+      return state.set("selectedLocation", _extends({
+        sourceId: action.source.id
+      }, action.location)).set("pendingSelectedLocation", location);
 
     case "CLEAR_SELECTED_SOURCE":
       location = { url: "" };
       _prefs.prefs.pendingSelectedLocation = location;
 
       return state.set("selectedLocation", { sourceId: "" }).set("pendingSelectedLocation", location);
 
     case "SELECT_SOURCE_URL":
@@ -19001,17 +19006,16 @@ exports.selectSource = selectSource;
 exports.jumpToMappedLocation = jumpToMappedLocation;
 exports.addTab = addTab;
 exports.moveTab = moveTab;
 exports.closeTab = closeTab;
 exports.closeTabs = closeTabs;
 exports.togglePrettyPrint = togglePrettyPrint;
 exports.toggleBlackBox = toggleBlackBox;
 exports.loadAllSources = loadAllSources;
-exports.ensureParserHasSourceText = ensureParserHasSourceText;
 
 var _promise = __webpack_require__(1370);
 
 var _assert = __webpack_require__(1384);
 
 var _assert2 = _interopRequireDefault(_assert);
 
 var _breakpoints = __webpack_require__(1396);
@@ -19029,47 +19033,39 @@ var _createPrettySource = __webpack_requ
 var _loadSourceText = __webpack_require__(1435);
 
 var _prefs = __webpack_require__(226);
 
 var _editor = __webpack_require__(1358);
 
 var _sourceMaps = __webpack_require__(1397);
 
-var _parser = __webpack_require__(1365);
-
-var parser = _interopRequireWildcard(_parser);
-
-var _selectors = __webpack_require__(1352);
-
-function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+var _selectors = __webpack_require__(1352);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 // If a request has been made to show this source, go ahead and
 // select it.
-
+async function checkSelectedSource(state, dispatch, source) {
+  const pendingLocation = (0, _selectors.getPendingSelectedLocation)(state);
+
+  if (pendingLocation && !!source.url && pendingLocation.url === source.url) {
+    await dispatch(selectSource(source.id, { location: pendingLocation }));
+  }
+}
 
 /* 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/. */
 
 /**
  * Redux actions for the sources state
  * @module actions/sources
  */
 
-async function checkSelectedSource(state, dispatch, source) {
-  const pendingLocation = (0, _selectors.getPendingSelectedLocation)(state);
-
-  if (pendingLocation && !!source.url && pendingLocation.url === source.url) {
-    await dispatch(selectSource(source.id, { line: pendingLocation.line }));
-  }
-}
-
 async function checkPendingBreakpoints(state, dispatch, sourceId) {
   // source may have been modified by selectSource
   const source = (0, _selectors.getSource)(state, sourceId).toJS();
   const pendingBreakpoints = (0, _selectors.getPendingBreakpointsForSource)(state, source.url);
   if (!pendingBreakpoints.size) {
     return;
   }
 
@@ -19132,16 +19128,17 @@ function loadSourceMap(generatedSource) 
       isPrettyPrinted: false,
       isWasm: false,
       isBlackBoxed: false,
       loadedState: "unloaded"
     }));
 
     dispatch({ type: "ADD_SOURCES", sources: originalSources });
 
+    await dispatch((0, _loadSourceText.loadSourceText)(generatedSource));
     originalSources.forEach(async source => {
       await checkSelectedSource(getState(), dispatch, source);
       checkPendingBreakpoints(getState(), dispatch, source.id);
     });
   };
 }
 
 /**
@@ -19158,17 +19155,17 @@ function selectSourceURL(url, options = 
     const source = (0, _selectors.getSourceByURL)(getState(), url);
     if (source) {
       await dispatch(selectSource(source.get("id"), options));
     } else {
       dispatch({
         type: "SELECT_SOURCE_URL",
         url: url,
         tabIndex: options.tabIndex,
-        line: options.line
+        location: options.location
       });
     }
   };
 }
 
 /**
  * @memberof actions/sources
  * @static
@@ -19193,17 +19190,17 @@ function selectSource(id, options = {}) 
     }
 
     dispatch(addTab(source.toJS(), 0));
 
     return dispatch({
       type: "SELECT_SOURCE",
       source: source.toJS(),
       tabIndex: options.tabIndex,
-      line: options.line,
+      location: options.location || {},
       [_promise.PROMISE]: (async () => {
         await dispatch((0, _loadSourceText.loadSourceText)(source.toJS()));
         await dispatch((0, _ast.setOutOfScopeLocations)());
       })()
     });
   };
 }
 
@@ -19220,17 +19217,17 @@ function jumpToMappedLocation(sourceLoca
     const source = (0, _selectors.getSource)(getState(), sourceLocation.sourceId);
     let pairedLocation;
     if (sourceMaps.isOriginalId(sourceLocation.sourceId)) {
       pairedLocation = await (0, _sourceMaps.getGeneratedLocation)(getState(), source.toJS(), sourceLocation, sourceMaps);
     } else {
       pairedLocation = await sourceMaps.getOriginalLocation(sourceLocation, source.toJS());
     }
 
-    return dispatch(selectSource(pairedLocation.sourceId, { line: pairedLocation.line }));
+    return dispatch(selectSource(pairedLocation.sourceId, { location: pairedLocation }));
   };
 }
 
 function addTab(source, tabIndex) {
   return {
     type: "ADD_TAB",
     source,
     tabIndex
@@ -19306,28 +19303,25 @@ function togglePrettyPrint(sourceId) {
     const selectedLocation = (0, _selectors.getSelectedLocation)(getState());
     const selectedOriginalLocation = selectedLocation ? await sourceMaps.getOriginalLocation(selectedLocation) : {};
 
     const url = (0, _source2.getPrettySourceURL)(source.url);
     const prettySource = (0, _selectors.getSourceByURL)(getState(), url);
 
     if (prettySource) {
       return dispatch(selectSource(prettySource.get("id"), {
-        line: selectedOriginalLocation.line
+        location: selectedOriginalLocation
       }));
     }
 
-    const { source: newPrettySource } = await dispatch((0, _createPrettySource.createPrettySource)(sourceId));
-
+    const newPrettySource = await dispatch((0, _createPrettySource.createPrettySource)(sourceId));
     await dispatch((0, _breakpoints.remapBreakpoints)(sourceId));
     await dispatch((0, _ast.setEmptyLines)(newPrettySource.id));
 
-    return dispatch(selectSource(newPrettySource.id, {
-      line: selectedOriginalLocation.line
-    }));
+    return dispatch(selectSource(newPrettySource.id, { location: selectedOriginalLocation }));
   };
 }
 
 function toggleBlackBox(source) {
   return async ({ dispatch, getState, client, sourceMaps }) => {
     const { isBlackBoxed, id } = source;
 
     return dispatch({
@@ -19358,31 +19352,16 @@ function loadAllSources() {
       // each of the source texts as they get loaded
       if (query) {
         await dispatch((0, _projectTextSearch.searchSource)(source.id, query));
       }
     }
   };
 }
 
-/**
- * Ensures parser has source text
- *
- * @memberof actions/sources
- * @static
- */
-function ensureParserHasSourceText(sourceId) {
-  return async ({ dispatch, getState }) => {
-    if (!(await parser.hasSource(sourceId))) {
-      await dispatch((0, _loadSourceText.loadSourceText)((0, _selectors.getSource)(getState(), sourceId).toJS()));
-      await parser.setSource((0, _selectors.getSource)(getState(), sourceId).toJS());
-    }
-  };
-}
-
 /***/ }),
 /* 1374 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
@@ -19500,17 +19479,16 @@ module.exports = {
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.getHiddenBreakpointLocation = exports.getHiddenBreakpoint = undefined;
 
 var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
 /* 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/. */
 
 /**
  * Breakpoints reducer
@@ -19519,31 +19497,31 @@ var _extends = Object.assign || function
 
 exports.initialState = initialState;
 exports.getBreakpoints = getBreakpoints;
 exports.getBreakpoint = getBreakpoint;
 exports.getBreakpointsDisabled = getBreakpointsDisabled;
 exports.getBreakpointsLoading = getBreakpointsLoading;
 exports.getBreakpointsForSource = getBreakpointsForSource;
 exports.getBreakpointForLine = getBreakpointForLine;
+exports.getHiddenBreakpoint = getHiddenBreakpoint;
+exports.getHiddenBreakpointLocation = getHiddenBreakpointLocation;
 
 var _immutable = __webpack_require__(146);
 
 var I = _interopRequireWildcard(_immutable);
 
 var _makeRecord = __webpack_require__(1361);
 
 var _makeRecord2 = _interopRequireDefault(_makeRecord);
 
 var _devtoolsSourceMap = __webpack_require__(1360);
 
 var _breakpoint = __webpack_require__(1364);
 
-var _reselect = __webpack_require__(993);
-
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
 
 function initialState() {
   return (0, _makeRecord2.default)({
     breakpoints: I.Map(),
     breakpointsDisabled: false
@@ -19684,27 +19662,27 @@ function getBreakpointsForSource(state, 
 function getBreakpointForLine(state, sourceId, line) {
   if (!sourceId) {
     return I.Map();
   }
   const breakpoints = getBreakpointsForSource(state, sourceId);
   return breakpoints.find(breakpoint => breakpoint.location.line === line);
 }
 
-const getHiddenBreakpoint = exports.getHiddenBreakpoint = (0, _reselect.createSelector)(getBreakpoints, function (breakpoints) {
-  const hiddenBreakpoints = breakpoints.valueSeq().filter(breakpoint => breakpoint.hidden).first();
-  return hiddenBreakpoints;
-});
-
-const getHiddenBreakpointLocation = exports.getHiddenBreakpointLocation = (0, _reselect.createSelector)(getHiddenBreakpoint, function (hiddenBreakpoint) {
+function getHiddenBreakpoint(state) {
+  return getBreakpoints(state).valueSeq().filter(breakpoint => breakpoint.hidden).first();
+}
+
+function getHiddenBreakpointLocation(state) {
+  const hiddenBreakpoint = getHiddenBreakpoint(state);
   if (!hiddenBreakpoint) {
     return null;
   }
   return hiddenBreakpoint.location;
-});
+}
 
 exports.default = update;
 
 /***/ }),
 /* 1379 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -19732,17 +19710,17 @@ var _Close = __webpack_require__(1374);
 
 var _Close2 = _interopRequireDefault(_Close);
 
 __webpack_require__(1313);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 const arrowBtn = (onClick, type, className, tooltip) => {
-  var props = {
+  const props = {
     onClick,
     type,
     className,
     title: tooltip,
     key: type
   };
 
   return _react2.default.createElement(
@@ -19751,20 +19729,26 @@ const arrowBtn = (onClick, type, classNa
     _react2.default.createElement(_Svg2.default, { name: type })
   );
 };
 
 class SearchInput extends _react.Component {
 
   componentDidMount() {
     this.$input.focus();
+    if (this.$input.value != "") {
+      this.$input.setSelectionRange(this.$input.value.length + 1, this.$input.value.length + 1);
+    }
   }
 
   componentDidUpdate() {
     this.$input.focus();
+    if (this.$input.value != "") {
+      this.$input.setSelectionRange(this.$input.value.length + 1, this.$input.value.length + 1);
+    }
   }
 
   shouldShowErrorEmoji() {
     const { count, query, showErrorEmoji } = this.props;
     return count === 0 && query.trim() !== "" && !showErrorEmoji;
   }
 
   renderSvg() {
@@ -19842,17 +19826,16 @@ class SearchInput extends _react.Compone
     );
   }
 }
 
 SearchInput.defaultProps = {
   size: "",
   showErrorEmoji: true
 };
-
 exports.default = SearchInput;
 
 /***/ }),
 /* 1380 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -19874,178 +19857,93 @@ var _devtoolsConfig = __webpack_require_
 var _utils = __webpack_require__(1366);
 
 var _source = __webpack_require__(1356);
 
 function getFrameUrl(frame) {
   return (0, _lodash.get)(frame, "source.url", "") || "";
 }
 
-function isBackbone(frame) {
-  return getFrameUrl(frame).match(/backbone/i);
-}
-
-function isJQuery(frame) {
-  return getFrameUrl(frame).match(/jquery/i);
-}
-
-function isReact(frame) {
-  return getFrameUrl(frame).match(/react/i);
-}
-
-function isImmutable(frame) {
-  return getFrameUrl(frame).match(/immutable/i);
-}
-
-function isWebpack(frame) {
-  return getFrameUrl(frame).match(/webpack\/bootstrap/i);
-}
-
-function isNodeInternal(frame) {
-  // starts with "internal/" OR no path, just "timers.js", "url.js" etc
-  // (normally frameUrl will be a FQ pathname)
-  return (/(^internal\/|^[^.\/]+\.js)/.test(getFrameUrl(frame))
-  );
-}
-
-function isExpress(frame) {
-  return (/node_modules\/express/.test(getFrameUrl(frame))
-  );
-}
-
-function isPug(frame) {
-  return (/node_modules\/pug/.test(getFrameUrl(frame))
-  );
-}
-
-function isExtJs(frame) {
-  return (/\/ext-all[\.\-]/.test(getFrameUrl(frame))
-  );
-}
-
-function isUnderscore(frame) {
-  return getFrameUrl(frame).match(/underscore/i);
-}
-
-function isLodash(frame) {
-  return getFrameUrl(frame).match(/lodash/i);
-}
-
-function isEmber(frame) {
-  return getFrameUrl(frame).match(/ember/i);
-}
-
-function isChoo(frame) {
-  return getFrameUrl(frame).match(/choo/i);
-}
-
-function isVueJS(frame) {
-  return getFrameUrl(frame).match(/vue\.js/i);
-}
-
-function isRxJs(frame) {
-  return getFrameUrl(frame).match(/rxjs/i);
-}
-
-function isAngular(frame) {
-  return getFrameUrl(frame).match(/angular/i);
-}
-
-function isRedux(frame) {
-  return getFrameUrl(frame).match(/redux/i);
-}
-
-function isDojo(frame) {
-  return getFrameUrl(frame).match(/dojo/i);
-}
-
-function isPreact(frame) {
-  return getFrameUrl(frame).match(/preact/i);
-}
+const libraryMap = [{
+  label: "Backbone",
+  pattern: /backbone/i
+}, {
+  label: "jQuery",
+  pattern: /jquery/i
+}, {
+  label: "Preact",
+  pattern: /preact/i
+}, {
+  label: "React",
+  pattern: /react/i
+}, {
+  label: "Immutable",
+  pattern: /immutable/i
+}, {
+  label: "Webpack",
+  pattern: /webpack\/bootstrap/i
+}, {
+  label: "Node",
+  pattern: /(^internal\/|^[^.\/]+\.js)/
+}, {
+  label: "Express",
+  pattern: /node_modules\/express/
+}, {
+  label: "Pug",
+  pattern: /node_modules\/pug/
+}, {
+  label: "ExtJS",
+  pattern: /\/ext-all[\.\-]/
+}, {
+  label: "Underscore",
+  pattern: /underscore/i
+}, {
+  label: "Lodash",
+  pattern: /lodash/i
+}, {
+  label: "Ember",
+  pattern: /ember/i
+}, {
+  label: "Choo",
+  pattern: /choo/i
+}, {
+  label: "VueJS",
+  pattern: /vue\.js/i
+}, {
+  label: "RxJS",
+  pattern: /rxjs/i
+}, {
+  label: "Angular",
+  pattern: /angular/i
+}, {
+  label: "Redux",
+  pattern: /redux/i
+}, {
+  label: "Dojo",
+  pattern: /dojo/i
+}, {
+  label: "Marko",
+  pattern: /marko/i
+}, {
+  label: "NuxtJS",
+  pattern: /[\._]nuxt/i
+}, {
+  label: "Aframe",
+  pattern: /aframe/i
+}, {
+  label: "NextJS",
+  pattern: /[\._]next/i
+}];
 
 function getLibraryFromUrl(frame) {
   // @TODO each of these fns calls getFrameUrl, just call it once
   // (assuming there's not more complex logic to identify a lib)
-
-  if (isBackbone(frame)) {
-    return "Backbone";
-  }
-
-  if (isJQuery(frame)) {
-    return "jQuery";
-  }
-
-  // Needs to remain before "react", otherwise "react" can also match "preact"
-  if (isPreact(frame)) {
-    return "Preact";
-  }
-
-  if (isReact(frame)) {
-    return "React";
-  }
-
-  if (isWebpack(frame)) {
-    return "Webpack";
-  }
-
-  if (isNodeInternal(frame)) {
-    return "Node";
-  }
-
-  if (isExpress(frame)) {
-    return "Express";
-  }
-
-  if (isChoo(frame)) {
-    return "Choo";
-  }
-
-  if (isPug(frame)) {
-    return "Pug";
-  }
-
-  if (isExtJs(frame)) {
-    return "ExtJS";
-  }
-
-  if (isUnderscore(frame)) {
-    return "Underscore";
-  }
-
-  if (isLodash(frame)) {
-    return "Lodash";
-  }
-
-  if (isEmber(frame)) {
-    return "Ember";
-  }
-
-  if (isVueJS(frame)) {
-    return "VueJS";
-  }
-
-  if (isRxJs(frame)) {
-    return "RxJS";
-  }
-
-  if (isAngular(frame)) {
-    return "Angular";
-  }
-
-  if (isRedux(frame)) {
-    return "Redux";
-  }
-
-  if (isDojo(frame)) {
-    return "Dojo";
-  }
-
-  if (isImmutable(frame)) {
-    return "Immutable";
-  }
+  const frameUrl = getFrameUrl(frame);
+  const match = (0, _lodash.find)(libraryMap, o => frameUrl.match(o.pattern));
+  return match && match.label;
 }
 
 const displayNameMap = {
   Backbone: {
     "extend/child": "Create Class",
     ".create": "Create Model"
   },
   jQuery: {
@@ -20165,17 +20063,17 @@ function collapseFrames(frames) {
   }
 
   items = addGroupToList(currentGroup, items);
   items = addGroupToList(lastGroup, items);
   return items;
 }
 
 function collapseLastFrames(frames) {
-  const index = (0, _lodash.findIndex)(frames, isWebpack);
+  const index = (0, _lodash.findIndex)(frames, frame => getFrameUrl(frame).match(/webpack\/bootstrap/i));
 
   if (index == -1) {
     return { newFrames: frames, lastGroup: [] };
   }
 
   const newFrames = frames.slice(0, index);
   const lastGroup = frames.slice(index);
   return { newFrames, lastGroup };
@@ -20587,48 +20485,36 @@ function assert(condition, message) {
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.setContextMenu = setContextMenu;
 exports.closeActiveSearch = closeActiveSearch;
 exports.setActiveSearch = setActiveSearch;
 exports.toggleFrameworkGrouping = toggleFrameworkGrouping;
-exports.setSelectedSymbolType = setSelectedSymbolType;
 exports.showSource = showSource;
 exports.togglePaneCollapse = togglePaneCollapse;
 exports.highlightLineRange = highlightLineRange;
 exports.clearHighlightLineRange = clearHighlightLineRange;
 exports.openConditionalPanel = openConditionalPanel;
 exports.closeConditionalPanel = closeConditionalPanel;
 exports.setProjectDirectoryRoot = setProjectDirectoryRoot;
 exports.setOrientation = setOrientation;
 
 var _selectors = __webpack_require__(1352);
 
-var _sourceSearch = __webpack_require__(1434);
-
 function setContextMenu(type, event) {
   return ({ dispatch }) => {
     dispatch({ type: "SET_CONTEXT_MENU", contextMenu: { type, event } });
   };
 }
-
 function closeActiveSearch() {
-  return ({ getState, dispatch }) => {
-    const activeSearch = (0, _selectors.getActiveSearch)(getState());
-
-    if (activeSearch == "source") {
-      dispatch((0, _sourceSearch.clearSourceSearchQuery)());
-    }
-
-    dispatch({
-      type: "TOGGLE_ACTIVE_SEARCH",
-      value: null
-    });
+  return {
+    type: "TOGGLE_ACTIVE_SEARCH",
+    value: null
   };
 }
 
 function setActiveSearch(activeSearch) {
   return ({ dispatch, getState }) => {
     const activeSearchState = (0, _selectors.getActiveSearch)(getState());
     if (activeSearchState === activeSearch) {
       return;
@@ -20645,25 +20531,16 @@ function toggleFrameworkGrouping(toggleV
   return ({ dispatch, getState }) => {
     dispatch({
       type: "TOGGLE_FRAMEWORK_GROUPING",
       value: toggleValue
     });
   };
 }
 
-function setSelectedSymbolType(symbolType) {
-  return ({ dispatch, getState }) => {
-    dispatch({
-      type: "SET_SYMBOL_SEARCH_TYPE",
-      symbolType
-    });
-  };
-}
-
 function showSource(sourceId) {
   return ({ dispatch, getState }) => {
     const source = (0, _selectors.getSource)(getState(), sourceId);
 
     dispatch({
       type: "SHOW_SOURCE",
       sourceUrl: ""
     });
@@ -21110,19 +20987,21 @@ exports.join = join;
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.getSelectedFrame = exports.getSelectedFrameId = exports.getLoadedObjects = exports.getPause = exports.State = undefined;
+exports.getSelectedFrame = exports.getLoadedObjects = exports.getPause = exports.State = undefined;
 
 var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+/* eslint complexity: ["error", 30]*/
+
 /* 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/. */
 
 /**
  * Pause reducer
  * @module reducers/pause
  */
@@ -21133,16 +21012,18 @@ exports.isEvaluatingExpression = isEvalu
 exports.pausedInEval = pausedInEval;
 exports.getLoadedObject = getLoadedObject;
 exports.getObjectProperties = getObjectProperties;
 exports.getIsWaitingOnBreak = getIsWaitingOnBreak;
 exports.getShouldPauseOnExceptions = getShouldPauseOnExceptions;
 exports.getShouldIgnoreCaughtExceptions = getShouldIgnoreCaughtExceptions;
 exports.getFrames = getFrames;
 exports.getFrameScopes = getFrameScopes;
+exports.getScopes = getScopes;
+exports.getSelectedFrameId = getSelectedFrameId;
 exports.getDebuggeeUrl = getDebuggeeUrl;
 exports.getChromeScopes = getChromeScopes;
 
 var _reselect = __webpack_require__(993);
 
 var _prefs = __webpack_require__(226);
 
 const State = exports.State = () => ({
@@ -21184,16 +21065,23 @@ function update(state = State(), action)
           pause: pauseInfo,
           selectedFrameId,
           frames,
           frameScopes,
           loadedObjects: objectMap
         });
       }
 
+    case "MAP_SCOPES":
+      const { frame, scopes } = action;
+      const selectedFrameId = frame.id;
+
+      return _extends({}, state, {
+        frameScopes: _extends({}, state.frameScopes, { [selectedFrameId]: scopes })
+      });
     case "RESUME":
       return Object.assign({}, state, {
         pause: null,
         frames: null,
         selectedFrameId: null,
         loadedObjects: {}
       });
 
@@ -21208,21 +21096,18 @@ function update(state = State(), action)
         return Object.assign({}, state, { pause, frames });
       }
 
       break;
     case "BREAK_ON_NEXT":
       return Object.assign({}, state, { isWaitingOnBreak: true });
 
     case "SELECT_FRAME":
-      const { frame, scopes } = action;
-      const selectedFrameId = frame.id;
       return _extends({}, state, {
-        frameScopes: _extends({}, state.frameScopes, { [selectedFrameId]: scopes }),
-        selectedFrameId
+        selectedFrameId: action.frame.id
       });
 
     case "LOAD_OBJECT_PROPERTIES":
       if (action.status === "start") {
         return _extends({}, state, {
           loadedObjects: _extends({}, state.loadedObjects, {
             [action.objectId]: {}
           })
@@ -21343,19 +21228,24 @@ function getShouldIgnoreCaughtExceptions
 function getFrames(state) {
   return state.pause.frames;
 }
 
 function getFrameScopes(state, frameId) {
   return state.pause.frameScopes[frameId];
 }
 
-const getSelectedFrameId = exports.getSelectedFrameId = (0, _reselect.createSelector)(getPauseState, pauseWrapper => {
-  return pauseWrapper.selectedFrameId;
-});
+function getScopes(state) {
+  const selectedFrameId = getSelectedFrameId(state);
+  return state.pause.frameScopes[selectedFrameId];
+}
+
+function getSelectedFrameId(state) {
+  return state.pause.selectedFrameId;
+}
 
 const getSelectedFrame = exports.getSelectedFrame = (0, _reselect.createSelector)(getSelectedFrameId, getFrames, (selectedFrameId, frames) => {
   if (!frames) {
     return null;
   }
   return frames.find(frame => frame.id == selectedFrameId);
 });
 
@@ -21822,18 +21712,16 @@ exports.evaluateExpressions = evaluateEx
 exports.getMappedExpression = getMappedExpression;
 
 var _selectors = __webpack_require__(1352);
 
 var _promise = __webpack_require__(1370);
 
 var _utils = __webpack_require__(1522);
 
-var _sources = __webpack_require__(1373);
-
 var _devtoolsSourceMap = __webpack_require__(1360);
 
 var _expressions = __webpack_require__(1437);
 
 var _parser = __webpack_require__(1365);
 
 var parser = _interopRequireWildcard(_parser);
 
@@ -21920,35 +21808,31 @@ function evaluateExpression(expression) 
     if (!expression.input) {
       console.warn("Expressions should not be empty");
       return;
     }
 
     let input = expression.input;
     const error = await parser.hasSyntaxError(input);
     if (error) {
-      debugger;
       return dispatch({
         type: "EVALUATE_EXPRESSION",
         input: expression.input,
         value: { input: expression.input, result: error }
       });
     }
 
     const frame = (0, _selectors.getSelectedFrame)(getState());
 
     if (frame) {
       const { location, generatedLocation } = frame;
       const source = (0, _selectors.getSource)(getState(), location.sourceId);
       const sourceId = source.get("id");
 
       if (!(0, _devtoolsSourceMap.isGeneratedId)(sourceId)) {
-        const generatedSourceId = generatedLocation.sourceId;
-        await dispatch((0, _sources.ensureParserHasSourceText)(generatedSourceId));
-
         input = await getMappedExpression({ sourceMaps }, generatedLocation, input);
       }
     }
 
     const frameId = (0, _selectors.getSelectedFrameId)(getState());
     return dispatch({
       type: "EVALUATE_EXPRESSION",
       input: expression.input,
@@ -21989,39 +21873,39 @@ var _extends = Object.assign || function
 exports.setSymbols = setSymbols;
 exports.setEmptyLines = setEmptyLines;
 exports.setOutOfScopeLocations = setOutOfScopeLocations;
 exports.clearPreview = clearPreview;
 exports.setPreview = setPreview;
 
 var _selectors = __webpack_require__(1352);
 
-var _sources = __webpack_require__(1373);
-
 var _expressions = __webpack_require__(1398);
 
 var _promise = __webpack_require__(1370);
 
 var _parser = __webpack_require__(1365);
 
+var _ast = __webpack_require__(1638);
+
 var _devtoolsSourceMap = __webpack_require__(1360);
 
 const extraProps = {
   react: { displayName: "this._reactInternalInstance.getName()" }
 };
 
 function setSymbols(sourceId) {
   return async ({ dispatch, getState }) => {
     const sourceRecord = (0, _selectors.getSource)(getState(), sourceId);
     if (!sourceRecord) {
       return;
     }
 
     const source = sourceRecord.toJS();
-    if (!source.text || (0, _selectors.hasSymbols)(getState(), source)) {
+    if (!source.text || source.isWasm || (0, _selectors.hasSymbols)(getState(), source)) {
       return;
     }
 
     const symbols = await (0, _parser.getSymbols)(source);
 
     dispatch({
       type: "SET_SYMBOLS",
       source,
@@ -22033,17 +21917,17 @@ function setSymbols(sourceId) {
 function setEmptyLines(sourceId) {
   return async ({ dispatch, getState }) => {
     const sourceRecord = (0, _selectors.getSource)(getState(), sourceId);
     if (!sourceRecord) {
       return;
     }
 
     const source = sourceRecord.toJS();
-    if (!source.text) {
+    if (!source.text || source.isWasm) {
       return;
     }
 
     const emptyLines = await (0, _parser.getEmptyLines)(source);
 
     dispatch({
       type: "SET_EMPTY_LINES",
       source,
@@ -22085,61 +21969,44 @@ function clearPreview() {
     }
 
     return dispatch({
       type: "CLEAR_SELECTION"
     });
   };
 }
 
-function findBestMatch(symbols, tokenPos, token) {
-  const { memberExpressions, identifiers } = symbols;
-  const { line, column } = tokenPos;
-  return identifiers.concat(memberExpressions).reduce((found, expression) => {
-    const overlaps = expression.location.start.line == line && expression.location.start.column <= column && expression.location.end.column >= column;
-
-    if (overlaps) {
-      return expression;
-    }
-
-    return found;
-  }, {});
-}
-
 function setPreview(token, tokenPos, cursorPos) {
   return async ({ dispatch, getState, client, sourceMaps }) => {
     const currentSelection = (0, _selectors.getPreview)(getState());
     if (currentSelection && currentSelection.updating) {
       return;
     }
 
     await dispatch({
       type: "SET_PREVIEW",
       [_promise.PROMISE]: async function () {
         const source = (0, _selectors.getSelectedSource)(getState());
         const _symbols = await (0, _parser.getSymbols)(source.toJS());
 
-        const found = findBestMatch(_symbols, tokenPos, token);
+        const found = (0, _ast.findBestMatchExpression)(_symbols, tokenPos, token);
         if (!found) {
           return;
         }
 
         let { expression, location } = found;
 
         if (!expression) {
           return;
         }
 
         const sourceId = source.get("id");
         if (location && !(0, _devtoolsSourceMap.isGeneratedId)(sourceId)) {
           const generatedLocation = await sourceMaps.getGeneratedLocation(_extends({}, location.start, { sourceId }), source.toJS());
 
-          const generatedSourceId = generatedLocation.sourceId;
-          await dispatch((0, _sources.ensureParserHasSourceText)(generatedSourceId));
-
           expression = await (0, _expressions.getMappedExpression)({ sourceMaps }, generatedLocation, expression);
         }
 
         const selectedFrame = (0, _selectors.getSelectedFrame)(getState());
         const { result } = await client.evaluate(expression, {
           frameId: selectedFrame.id
         });
 
@@ -22169,40 +22036,38 @@ function setPreview(token, tokenPos, cur
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
 exports.updateFrameLocations = updateFrameLocations;
 exports.updateScopeBindings = updateScopeBindings;
 exports.getPauseReason = getPauseReason;
 exports.getPausedPosition = getPausedPosition;
 
 var _lodash = __webpack_require__(2);
 
 var _parser = __webpack_require__(1365);
 
 function updateFrameLocations(frames, sourceMaps) {
   if (!frames || frames.length == 0) {
     return Promise.resolve(frames);
   }
 
-  return Promise.all(frames.map(frame => {
-    return sourceMaps.getOriginalLocation(frame.location).then(loc => {
-      return Object.assign({}, frame, {
-        location: loc,
-        generatedLocation: frame.location
-      });
-    });
-  }));
-}
-
+  return Promise.all(frames.map(frame => sourceMaps.getOriginalLocation(frame.location).then(loc => _extends({}, frame, {
+    location: loc,
+    generatedLocation: frame.location
+  }))));
+}
 
 function extendScope(scope, generatedScopes, index) {
   if (!scope) {
     return undefined;
   }
   if (index >= generatedScopes.length) {
     return scope;
   }
@@ -22509,17 +22374,17 @@ var _classnames2 = _interopRequireDefaul
 var _Transition = __webpack_require__(333);
 
 var _Transition2 = _interopRequireDefault(_Transition);
 
 __webpack_require__(1303);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
-class Modal extends _react.Component {
+class Modal extends _react2.default.Component {
   constructor(...args) {
     var _temp;
 
     return _temp = super(...args), this.onClick = e => {
       e.stopPropagation();
     }, _temp;
   }
 
@@ -22585,20 +22450,17 @@ var _react = __webpack_require__(0);
 var _react2 = _interopRequireDefault(_react);
 
 __webpack_require__(1311);
 
 var _devtoolsComponents = __webpack_require__(1441);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
-const Tree = (0, _react.createFactory)(_devtoolsComponents.Tree);
-
 class ManagedTree extends _react.Component {
-
   constructor(props) {
     super();
 
     this.setExpanded = (item, isExpanded, shouldIncludeChildren) => {
       const expandItem = i => {
         const path = this.props.getPath(i);
         if (isExpanded) {
           expanded.add(path);
@@ -22700,17 +22562,17 @@ class ManagedTree extends _react.Compone
         setExpanded: this.setExpanded
       })
     };
 
     const props = _extends({}, this.props, overrides);
     return _react2.default.createElement(
       "div",
       { className: "managed-tree" },
-      _react2.default.createElement(Tree, props)
+      _react2.default.createElement(_devtoolsComponents.Tree, props)
     );
   }
 }
 
 exports.default = ManagedTree;
 
 /***/ }),
 /* 1405 */
@@ -22826,17 +22688,17 @@ var _devtoolsConfig = __webpack_require_
 function scrollList(resultList, index) {
   if (!resultList.hasOwnProperty(index)) {
     return;
   }
 
   const resultEl = resultList[index];
 
   if ((0, _devtoolsConfig.isFirefox)()) {
-    resultEl.scrollIntoView({ block: "end", behavior: "smooth" });
+    resultEl.scrollIntoView({ block: "center", behavior: "smooth" });
   } else {
     chromeScrollList(resultEl, index);
   }
 }
 
 function chromeScrollList(elem, index) {
   const resultsEl = elem.parentNode;
   if (!resultsEl || resultsEl.children.length === 0) {
@@ -22878,17 +22740,16 @@ var _Svg = __webpack_require__(1359);
 
 var _Svg2 = _interopRequireDefault(_Svg);
 
 __webpack_require__(1321);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class PaneToggleButton extends _react.Component {
-
   shouldComponentUpdate(nextProps) {
     const { collapsed, horizontal } = this.props;
 
     return horizontal !== nextProps.horizontal || collapsed !== nextProps.collapsed;
   }
 
   render() {
     const { position, collapsed, horizontal, handleClick } = this.props;
@@ -23748,23 +23609,23 @@ var _makeRecord = __webpack_require__(13
 
 var _makeRecord2 = _interopRequireDefault(_makeRecord);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 const State = exports.State = (0, _makeRecord2.default)({
   workers: (0, _immutable.List)()
 });
-/* 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/. */
-
-/**
- * Debuggee reducer
- * @module reducers/debuggee
+/* 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/. */
+
+/**
+ * Debuggee reducer
+ * @module reducers/debuggee
  */
 
 function debuggee(state = State(), action) {
   switch (action.type) {
     case "SET_WORKERS":
       return state.set("workers", (0, _immutable.List)(action.workers.workers));
     default:
       return state;
@@ -23988,17 +23849,16 @@ exports.default = update;
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.State = undefined;
 exports.getActiveSearch = getActiveSearch;
 exports.getContextMenu = getContextMenu;
 exports.getFrameworkGroupingState = getFrameworkGroupingState;
-exports.getSymbolSearchType = getSymbolSearchType;
 exports.getShownSource = getShownSource;
 exports.getPaneCollapse = getPaneCollapse;
 exports.getHighlightedLineRange = getHighlightedLineRange;
 exports.getConditionalPanelLine = getConditionalPanelLine;
 exports.getProjectDirectoryRoot = getProjectDirectoryRoot;
 exports.getOrientation = getOrientation;
 
 var _makeRecord = __webpack_require__(1361);
@@ -24016,17 +23876,16 @@ function _interopRequireDefault(obj) { r
 /**
  * UI reducer
  * @module reducers/ui
  */
 
 const State = exports.State = (0, _makeRecord2.default)({
   activeSearch: null,
   contextMenu: {},
-  symbolSearchType: "functions",
   shownSource: "",
   projectDirectoryRoot: "",
   startPanelCollapsed: _prefs.prefs.startPanelCollapsed,
   endPanelCollapsed: _prefs.prefs.endPanelCollapsed,
   frameworkGroupingOn: _prefs.prefs.frameworkGroupingOn,
   highlightedLineRange: undefined,
   conditionalPanelLine: null,
   orientation: "horizontal"
@@ -24040,21 +23899,16 @@ function update(state = State(), action)
       }
 
     case "TOGGLE_FRAMEWORK_GROUPING":
       {
         _prefs.prefs.frameworkGroupingOn = action.value;
         return state.set("frameworkGroupingOn", action.value);
       }
 
-    case "SET_SYMBOL_SEARCH_TYPE":
-      {
-        return state.set("symbolSearchType", action.symbolType);
-      }
-
     case "SET_CONTEXT_MENU":
       {
         return state.set("contextMenu", action.contextMenu);
       }
 
     case "SET_ORIENTATION":
       {
         return state.set("orientation", action.orientation);
@@ -24115,20 +23969,16 @@ function getActiveSearch(state) {
 function getContextMenu(state) {
   return state.ui.get("contextMenu");
 }
 
 function getFrameworkGroupingState(state) {
   return state.ui.get("frameworkGroupingOn");
 }
 
-function getSymbolSearchType(state) {
-  return state.ui.get("symbolSearchType");
-}
-
 function getShownSource(state) {
   return state.ui.get("shownSource");
 }
 
 function getPaneCollapse(state, position) {
   if (position == "start") {
     return state.ui.get("startPanelCollapsed");
   }
@@ -24384,63 +24234,17 @@ function getTextSearchResults(state) {
 
 function getTextSearchQuery(state) {
   return state.projectTextSearch.get("query");
 }
 
 exports.default = update;
 
 /***/ }),
-/* 1425 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.default = update;
-exports.getSourceSearchQuery = getSourceSearchQuery;
-
-var _makeRecord = __webpack_require__(1361);
-
-var _makeRecord2 = _interopRequireDefault(_makeRecord);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function InitialState() {
-  return (0, _makeRecord2.default)({
-    queryString: ""
-  })();
-} /* 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/. */
-
-/**
- * Source search reducer
- * @module reducers/source-search
- */
-
-function update(state = InitialState(), action) {
-  switch (action.type) {
-    case "SET_QUERY_STRING":
-      return state.update("queryString", value => action.queryString);
-    case "CLEAR_QUERY_STRING":
-      return state.update("queryString", value => "");
-    default:
-      return state;
-  }
-}
-
-function getSourceSearchQuery(state) {
-  return state.sourceSearch.get("queryString");
-}
-
-/***/ }),
+/* 1425 */,
 /* 1426 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -24724,18 +24528,18 @@ var _App = __webpack_require__(1518);
 var _App2 = _interopRequireDefault(_App);
 
 var _prefs = __webpack_require__(226);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 function bootstrapStore(client, { services, toolboxActions }) {
   const createStore = (0, _createStore2.default)({
-    log: (0, _devtoolsConfig.getValue)("logging.actions"),
-    timing: (0, _devtoolsConfig.getValue)("performance.actions"),
+    log: (0, _devtoolsConfig.isTesting)() || (0, _devtoolsConfig.getValue)("logging.actions"),
+    timing: (0, _devtoolsConfig.isDevelopment)(),
     makeThunkArgs: (args, state) => {
       return Object.assign({}, args, { client }, services, toolboxActions);
     }
   });
 
   const store = createStore((0, _redux.combineReducers)(_reducers2.default));
   store.subscribe(() => updatePrefs(store.getState()));
 
@@ -24938,89 +24742,73 @@ function searchSource(sourceId, query) {
         filepath: source.url,
         matches
       }
     });
   };
 }
 
 /***/ }),
-/* 1434 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.setSourceSearchQuery = setSourceSearchQuery;
-exports.clearSourceSearchQuery = clearSourceSearchQuery;
-function setSourceSearchQuery(queryString) {
-  return ({ dispatch, getState }) => {
-    dispatch({
-      type: "SET_QUERY_STRING",
-      queryString
-    });
-  };
-}
-
-function clearSourceSearchQuery() {
-  return ({ dispatch, getState }) => {
-    dispatch({
-      type: "CLEAR_QUERY_STRING"
-    });
-  };
-}
-
-/***/ }),
+/* 1434 */,
 /* 1435 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.loadSourceText = loadSourceText;
 
 var _promise = __webpack_require__(1370);
 
 var _ast = __webpack_require__(1399);
 
+var _selectors = __webpack_require__(1352);
+
+var _parser = __webpack_require__(1365);
+
+async function loadSource(source, { sourceMaps, client }) {
+  if (sourceMaps.isOriginalId(source.id)) {
+    return await sourceMaps.getOriginalSourceText(source);
+  }
+
+  const response = await client.sourceContents(source.id);
+
+  return {
+    id: source.id,
+    text: response.source,
+    contentType: response.contentType || "text/javascript"
+  };
+}
+
 /**
  * @memberof actions/sources
  * @static
  */
 function loadSourceText(source) {
   return async ({ dispatch, getState, client, sourceMaps }) => {
     // Fetch the source text only once.
     if (source.text) {
       return Promise.resolve(source);
     }
 
     await dispatch({
       type: "LOAD_SOURCE_TEXT",
       source: source,
-      [_promise.PROMISE]: async function () {
-        if (sourceMaps.isOriginalId(source.id)) {
-          return await sourceMaps.getOriginalSourceText(source);
-        }
-
-        const response = await client.sourceContents(source.id);
-
-        return {
-          id: source.id,
-          text: response.source,
-          contentType: response.contentType || "text/javascript"
-        };
-      }()
-    });
-
+      [_promise.PROMISE]: loadSource(source, { sourceMaps, client })
+    });
+
+    const newSource = (0, _selectors.getSource)(getState(), source.id).toJS();
+    if (newSource.isWasm) {
+      return;
+    }
+
+    await (0, _parser.setSource)(newSource);
     await dispatch((0, _ast.setSymbols)(source.id));
     await dispatch((0, _ast.setEmptyLines)(source.id));
   };
 }
 
 /***/ }),
 /* 1436 */
 /***/ (function(module, exports, __webpack_require__) {
@@ -25032,19 +24820,17 @@ Object.defineProperty(exports, "__esModu
   value: true
 });
 exports.showLoading = exports.showSourceText = exports.updateDocument = exports.updateLineNumberFormat = exports.resetLineNumberFormat = exports.clearDocuments = exports.removeDocument = exports.setDocument = exports.getDocument = undefined;
 
 var _source = __webpack_require__(1356);
 
 var _wasm = __webpack_require__(1401);
 
-var _devtoolsSourceEditor = __webpack_require__(1386);
-
-const { resizeBreakpointGutter } = _devtoolsSourceEditor.SourceEditorUtils;
+var _ui = __webpack_require__(1439);
 
 let sourceDocs = {};
 
 function getDocument(key) {
   return sourceDocs[key];
 }
 
 function setDocument(key, doc) {
@@ -25057,27 +24843,29 @@ function removeDocument(key) {
 
 function clearDocuments() {
   sourceDocs = {};
 }
 
 function resetLineNumberFormat(editor) {
   const cm = editor.codeMirror;
   cm.setOption("lineNumberFormatter", number => number);
-  resizeBreakpointGutter(cm);
+  (0, _ui.resizeBreakpointGutter)(cm);
+  (0, _ui.resizeToggleButton)(cm);
 }
 
 function updateLineNumberFormat(editor, sourceId) {
   if (!(0, _wasm.isWasm)(sourceId)) {
     return resetLineNumberFormat(editor);
   }
   const cm = editor.codeMirror;
   const lineNumberFormatter = (0, _wasm.getWasmLineNumberFormatter)(sourceId);
   cm.setOption("lineNumberFormatter", lineNumberFormatter);
-  resizeBreakpointGutter(cm);
+  (0, _ui.resizeBreakpointGutter)(cm);
+  (0, _ui.resizeToggleButton)(cm);
 }
 
 function updateDocument(editor, sourceId) {
   if (!sourceId) {
     return;
   }
 
   const doc = getDocument(sourceId) || editor.createDocument();
@@ -25162,17 +24950,17 @@ Object.defineProperty(exports, "__esModu
 exports.sanitizeInput = sanitizeInput;
 exports.wrapExpression = wrapExpression;
 exports.getValue = getValue;
 
 var _indentation = __webpack_require__(1438);
 
 // replace quotes and slashes that could interfere with the evaluation.
 function sanitizeInput(input) {
-  return input.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
+  return input.replace(/\\/g, "\\\\").replace(/"/g, '"');
 }
 
 /*
  * wrap the expression input in a try/catch so that it can be safely
  * evaluated.
  *
  * NOTE: we add line after the expression to protect against comments.
 */
@@ -25268,34 +25056,67 @@ function correctIndentation(text) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.isVisible = isVisible;
+exports.getLineNumberWidth = getLineNumberWidth;
+exports.resizeBreakpointGutter = resizeBreakpointGutter;
+exports.resizeToggleButton = resizeToggleButton;
 /* Checks to see if the root element is available and
  * if the element is visible. We check the width of the element
  * because it is more reliable than either checking a focus state or
  * the visibleState or hidden property.
  */
 function isVisible() {
   const el = document.querySelector("#mount");
   return el && el.getBoundingClientRect().width;
 }
 
+/* Gets the line numbers width in the code editor
+ */
+function getLineNumberWidth(editor) {
+  const gutters = editor.display.gutters;
+  const lineNumbers = gutters.querySelector(".CodeMirror-linenumbers");
+  return lineNumbers && lineNumbers.clientWidth;
+}
+
+/**
+ * Forces the breakpoint gutter to be the same size as the line
+ * numbers gutter. Editor CSS will absolutely position the gutter
+ * beneath the line numbers. This makes it easy to be flexible with
+ * how we overlay breakpoints.
+ */
+function resizeBreakpointGutter(editor) {
+  const gutters = editor.display.gutters;
+  const breakpoints = gutters.querySelector(".breakpoints");
+  if (breakpoints) {
+    breakpoints.style.width = `${getLineNumberWidth(editor)}px`;
+  }
+}
+
+/**
+ * Forces the left toggle button in source header to be the same size
+ * as the line numbers gutter.
+ */
+function resizeToggleButton(editor) {
+  const toggleButton = document.querySelector(".source-header .toggle-button-start");
+  if (toggleButton) {
+    toggleButton.style.width = `${getLineNumberWidth(editor)}px`;
+  }
+}
+
 /***/ }),
 /* 1440 */
 /***/ (function(module, exports, __webpack_require__) {
 
-"use strict";
-
-
-var SplitBox = __webpack_require__(1536);
+const SplitBox = __webpack_require__(1536);
 
 module.exports = SplitBox;
 
 /***/ }),
 /* 1441 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -25631,17 +25452,17 @@ class ResultList extends _react.Componen
     this.renderListItem = this.renderListItem.bind(this);
   }
 
   renderListItem(item, index) {
     const { selectItem, selected } = this.props;
     const props = {
       onClick: event => selectItem(event, item, index),
       key: `${item.id}${item.value}${index}`,
-      ref: index,
+      ref: String(index),
       title: item.value,
       className: (0, _classnames2.default)("result-item", {
         selected: index === selected
       })
     };
 
     return _react2.default.createElement(
       "li",
@@ -25664,17 +25485,16 @@ class ResultList extends _react.Componen
 
     return _react2.default.createElement(
       "ul",
       { className: (0, _classnames2.default)("result-list", size) },
       items.map(this.renderListItem)
     );
   }
 }
-
 exports.default = ResultList;
 ResultList.defaultProps = {
   size: "small"
 };
 
 /***/ }),
 /* 1446 */
 /***/ (function(module, exports, __webpack_require__) {
@@ -26907,20 +26727,16 @@ function FrameLocation({ frame }) {
     `${filename}: ${frame.location.line}`
   );
 }
 
 FrameLocation.displayName = "FrameLocation";
 
 class FrameComponent extends _react.Component {
 
-  constructor() {
-    super();
-  }
-
   onContextMenu(event) {
     const {
       frame,
       copyStackTrace,
       toggleFrameworkGrouping,
       toggleBlackBox,
       frameworkGroupingOn
     } = this.props;
@@ -26968,17 +26784,16 @@ class FrameComponent extends _react.Comp
   }
 }
 
 exports.default = FrameComponent;
 FrameComponent.defaultProps = {
   hideLocation: false,
   shouldMapDisplayName: true
 };
-
 FrameComponent.displayName = "Frame";
 
 /***/ }),
 /* 1454 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -31638,26 +31453,94 @@ function waitUntilService({ dispatch, ge
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
 exports.log = log;
+
+var _devtoolsConfig = __webpack_require__(1355);
+
+const blacklist = ["LOAD_OBJECT_PROPERTIES", "SET_SYMBOLS", "OUT_OF_SCOPE_LOCATIONS"];
+
+function cloneAction(action) {
+  action = action || {};
+  action = _extends({}, action);
+
+  // ADD_TAB, ...
+  if (action.source && action.source.text) {
+    const source = _extends({}, action.source, { text: "" });
+    action.source = source;
+  }
+
+  // LOAD_SOURCE_TEXT
+  if (action.text) {
+    action.text = "";
+  }
+
+  if (action.value && action.value.text) {
+    const value = _extends({}, action.value, { text: "" });
+    action.value = value;
+  }
+
+  return action;
+}
+
+function formatFrame(frame) {
+  const { id, location, displayName } = frame;
+  return { id, location, displayName };
+}
+
+function formatPause(pause) {
+  return _extends({}, pause, {
+    pauseInfo: { why: pause.pauseInfo.why },
+    scopes: [],
+    frames: pause.frames.map(formatFrame),
+    loadedObjects: []
+  });
+}
+
+function serializeAction(action) {
+  try {
+    action = cloneAction(action);
+    if (blacklist.includes(action.type)) {
+      action = {};
+    }
+
+    if (action.type === "PAUSED") {
+      action = formatPause(action);
+    }
+
+    // dump(`> ${action.type}...\n ${JSON.stringify(action)}\n`);
+    return JSON.stringify(action);
+  } catch (e) {
+    console.error(e);
+  }
+}
+
 /**
  * A middleware that logs all actions coming through the system
  * to the console.
  */
 function log({ dispatch, getState }) {
   return next => action => {
-    const status = action.status == "done" ? "<-" : "->";
-    const asyncMsg = !action.status ? "" : status;
-    console.log(action, asyncMsg);
+    const asyncMsg = !action.status ? "" : `[${action.status}]`;
+
+    if ((0, _devtoolsConfig.isTesting)()) {
+      dump(`[ACTION] ${action.type} ${asyncMsg} - ${serializeAction(action)}\n`);
+    } else {
+      console.log(action, asyncMsg);
+    }
+
     next(action);
   };
 }
 
 /***/ }),
 /* 1513 */
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -31803,19 +31686,19 @@ var _ast2 = _interopRequireDefault(_ast)
 var _coverage = __webpack_require__(1423);
 
 var _coverage2 = _interopRequireDefault(_coverage);
 
 var _projectTextSearch = __webpack_require__(1424);
 
 var _projectTextSearch2 = _interopRequireDefault(_projectTextSearch);
 
-var _sourceSearch = __webpack_require__(1425);
-
-var _sourceSearch2 = _interopRequireDefault(_sourceSearch);
+var _quickOpen = __webpack_require__(1635);
+
+var _quickOpen2 = _interopRequireDefault(_quickOpen);
 
 var _sourceTree = __webpack_require__(1426);
 
 var _sourceTree2 = _interopRequireDefault(_sourceTree);
 
 var _debuggee = __webpack_require__(1418);
 
 var _debuggee2 = _interopRequireDefault(_debuggee);
@@ -31830,17 +31713,17 @@ exports.default = {
   pendingBreakpoints: _pendingBreakpoints2.default,
   asyncRequests: _asyncRequests2.default,
   pause: _pause2.default,
   ui: _ui2.default,
   fileSearch: _fileSearch2.default,
   ast: _ast2.default,
   coverage: _coverage2.default,
   projectTextSearch: _projectTextSearch2.default,
-  sourceSearch: _sourceSearch2.default,
+  quickOpen: _quickOpen2.default,
   sourceTree: _sourceTree2.default,
   debuggee: _debuggee2.default
 }; /* 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/. */
 
 /**
  * Reducer index
@@ -31957,23 +31840,19 @@ var _SecondaryPanes2 = _interopRequireDe
 var _WelcomeBox = __webpack_require__(1613);
 
 var _WelcomeBox2 = _interopRequireDefault(_WelcomeBox);
 
 var _Tabs = __webpack_require__(1614);
 
 var _Tabs2 = _interopRequireDefault(_Tabs);
 
-var _SymbolModal = __webpack_require__(1616);
-
-var _SymbolModal2 = _interopRequireDefault(_SymbolModal);
-
-var _GotoLineModal = __webpack_require__(1617);
-
-var _GotoLineModal2 = _interopRequireDefault(_GotoLineModal);
+var _QuickOpenModal = __webpack_require__(1652);
+
+var _QuickOpenModal2 = _interopRequireDefault(_QuickOpenModal);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 const shortcuts = new _devtoolsModules.KeyShortcuts({ window });
 
 const { appinfo } = _devtoolsModules.Services;
 
 const isMacOS = appinfo.OS === "Darwin";
@@ -31987,112 +31866,102 @@ class App extends _react.Component {
     this.state = {
       shortcutsModalEnabled: false,
       startPanelSize: 0,
       endPanelSize: 0
     };
 
     this.getChildContext = this.getChildContext.bind(this);
     this.onLayoutChange = this.onLayoutChange.bind(this);
-    this.toggleSymbolModal = this.toggleSymbolModal.bind(this);
-    this.toggleGoToLineModal = this.toggleGoToLineModal.bind(this);
+    this.toggleQuickOpenModal = this.toggleQuickOpenModal.bind(this);
     this.renderEditorPane = this.renderEditorPane.bind(this);
     this.renderVerticalLayout = this.renderVerticalLayout.bind(this);
     this.onEscape = this.onEscape.bind(this);
     this.onCommandSlash = this.onCommandSlash.bind(this);
   }
 
   getChildContext() {
     return { shortcuts };
   }
 
   componentDidMount() {
     verticalLayoutBreakpoint.addListener(this.onLayoutChange);
 
-    shortcuts.on(L10N.getStr("symbolSearch.search.key2"), this.toggleSymbolModal);
-
-    shortcuts.on(L10N.getStr("gotoLineModal.key"), this.toggleGoToLineModal);
+    shortcuts.on(L10N.getStr("symbolSearch.search.key2"), (_, e) => this.toggleQuickOpenModal(_, e, "@"));
+
+    const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")];
+    searchKeys.forEach(key => shortcuts.on(key, this.toggleQuickOpenModal));
+
+    shortcuts.on(L10N.getStr("gotoLineModal.key"), (_, e) => this.toggleQuickOpenModal(_, e, ":"));
 
     shortcuts.on("Escape", this.onEscape);
     shortcuts.on("Cmd+/", this.onCommandSlash);
   }
 
   componentWillUnmount() {
     verticalLayoutBreakpoint.removeListener(this.onLayoutChange);
-    shortcuts.off(L10N.getStr("symbolSearch.search.key2"), this.toggleSymbolModal);
-
-    shortcuts.off(L10N.getStr("gotoLineModal.key"), this.toggleGoToLineModal);
+    shortcuts.off(L10N.getStr("symbolSearch.search.key2"), this.toggleQuickOpenModal);
+
+    const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")];
+    searchKeys.forEach(key => shortcuts.off(key, this.toggleQuickOpenModal));
+
+    shortcuts.off(L10N.getStr("gotoLineModal.key"), this.toggleQuickOpenModal);
 
     shortcuts.off("Escape", this.onEscape);
   }
 
   onEscape(_, e) {
-    const { activeSearch, closeActiveSearch } = this.props;
+    const {
+      activeSearch,
+      quickOpenEnabled,
+      closeActiveSearch,
+      closeQuickOpen
+    } = this.props;
 
     if (activeSearch) {
       e.preventDefault();
       closeActiveSearch();
     }
+
+    if (quickOpenEnabled === true) {
+      closeQuickOpen();
+    }
   }
 
   onCommandSlash() {
     this.toggleShortcutsModal();
   }
 
   isHorizontal() {
     return this.props.orientation === "horizontal";
   }
 
-  toggleSymbolModal(_, e) {
-    const {
-      selectedSource,
-      activeSearch,
-      closeActiveSearch,
-      setActiveSearch
-    } = this.props;
+  toggleQuickOpenModal(_, e, query) {
+    const { quickOpenEnabled, openQuickOpen, closeQuickOpen } = this.props;
 
     e.preventDefault();
     e.stopPropagation();
 
-    if (!selectedSource) {
-      return;
-    }
-
-    if (activeSearch == "symbol") {
-      return closeActiveSearch();
-    }
-
-    setActiveSearch("symbol");
-  }
-
-  toggleGoToLineModal(_, e) {
-    const {
-      selectedSource,
-      activeSearch,
-      closeActiveSearch,
-      setActiveSearch
-    } = this.props;
-
-    e.preventDefault();
-    e.stopPropagation();
-
-    if (!selectedSource) {
-      return;
-    }
-
-    if (activeSearch == "line") {
-      return closeActiveSearch();
-    }
-
-    setActiveSearch("line");
+    if (quickOpenEnabled === true) {
+      closeQuickOpen();
+      return;
+    }
+
+    if (query != null) {
+      openQuickOpen(query);
+      return;
+    }
+    openQuickOpen();
+    return;
   }
 
   onLayoutChange() {
+    const orientation = verticalLayoutBreakpoint.matches ? "horizontal" : "vertical";
     if ((0, _ui.isVisible)()) {
-      this.props.setOrientation(verticalLayoutBreakpoint.matches ? "horizontal" : "vertical");
+      this.props.setOrientation(orientation);
     }
   }
 
   renderEditorPane() {
     const { startPanelCollapsed, endPanelCollapsed } = this.props;
     const { endPanelSize, startPanelSize } = this.state;
     const horizontal = this.isHorizontal();
 
@@ -32184,76 +32053,51 @@ class App extends _react.Component {
       endPanel: _react2.default.createElement(_SecondaryPanes2.default, {
         horizontal: horizontal,
         toggleShortcutsModal: () => this.toggleShortcutsModal()
       }),
       endPanelCollapsed: endPanelCollapsed
     });
   }
 
-  renderSymbolModal() {
-    const { selectSource, selectedSource, activeSearch } = this.props;
-
-    if (activeSearch !== "symbol") {
-      return;
-    }
-
-    return _react2.default.createElement(_SymbolModal2.default, {
-      selectSource: selectSource,
-      selectedSource: selectedSource
-    });
-  }
-
-  renderGotoLineModal() {
-    const { selectSource, selectedSource, activeSearch } = this.props;
-
-    if (activeSearch !== "line") {
-      return;
-    }
-
-    return _react2.default.createElement(_GotoLineModal2.default, {
-      selectSource: selectSource,
-      selectedSource: selectedSource
-    });
-  }
-
   renderShortcutsModal() {
     const additionalClass = isMacOS ? "mac" : "";
 
     if (!_prefs.features.shortcuts) {
       return;
     }
 
     return _react2.default.createElement(_ShortcutsModal.ShortcutsModal, {
       additionalClass: additionalClass,
       enabled: this.state.shortcutsModalEnabled,
       handleClose: () => this.toggleShortcutsModal()
     });
   }
 
   render() {
+    const { quickOpenEnabled } = this.props;
     return _react2.default.createElement(
       "div",
       { className: "debugger" },
       this.isHorizontal() ? this.renderHorizontalLayout() : this.renderVerticalLayout(),
-      this.renderSymbolModal(),
-      this.renderGotoLineModal(),
+      quickOpenEnabled === true && _react2.default.createElement(_QuickOpenModal2.default, null),
       this.renderShortcutsModal()
     );
   }
 }
 
 App.childContextTypes = { shortcuts: _propTypes2.default.object };
 
 function mapStateToProps(state) {
   return {
     selectedSource: (0, _selectors.getSelectedSource)(state),
     startPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "start"),
     endPanelCollapsed: (0, _selectors.getPaneCollapse)(state, "end"),
     activeSearch: (0, _selectors.getActiveSearch)(state),
+    quickOpenEnabled: (0, _selectors.getQuickOpenEnabled)(state),
     orientation: (0, _selectors.getOrientation)(state)
   };
 }
 
 exports.default = (0, _reactRedux.connect)(mapStateToProps, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(App);
 
 /***/ }),
 /* 1519 */
@@ -32517,20 +32361,22 @@ function createPrettySource(sourceId) {
       id,
       isPrettyPrinted: true,
       text: code,
       contentType: "text/javascript",
       frames,
       loadedState: "loaded"
     };
 
-    return dispatch({
+    dispatch({
       type: "ADD_SOURCE",
       source: prettySource
     });
+
+    return prettySource;
   };
 }
 
 /***/ }),
 /* 1524 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -33115,338 +32961,17 @@ function updateEventBreakpoints(eventNam
           eventNames: eventNames
         });
       });
     });
   };
 }
 
 /***/ }),
-/* 1528 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.resumed = resumed;
-exports.continueToHere = continueToHere;
-exports.paused = paused;
-exports.pauseOnExceptions = pauseOnExceptions;
-exports.command = command;
-exports.stepIn = stepIn;
-exports.stepOver = stepOver;
-exports.stepOut = stepOut;
-exports.resume = resume;
-exports.breakOnNext = breakOnNext;
-exports.selectFrame = selectFrame;
-exports.loadObjectProperties = loadObjectProperties;
-exports.astCommand = astCommand;
-
-var _sources = __webpack_require__(1373);
-
-var _promise = __webpack_require__(1370);
-
-var _selectors = __webpack_require__(1352);
-
-var _pause = __webpack_require__(1400);
-
-var _expressions = __webpack_require__(1398);
-
-var _breakpoints = __webpack_require__(1396);
-
-var _breakpoints2 = __webpack_require__(1378);
-
-var _parser = __webpack_require__(1365);
-
-var parser = _interopRequireWildcard(_parser);
-
-var _prefs = __webpack_require__(226);
-
-var _devtoolsSourceMap = __webpack_require__(1360);
-
-function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
-
-async function _getScopeBindings({ dispatch, getState, sourceMaps }, generatedLocation, scopes) {
-  const { sourceId } = generatedLocation;
-  const sourceRecord = (0, _selectors.getSource)(getState(), sourceId);
-  if (sourceRecord.get("isWasm")) {
-    return scopes;
-  }
-
-  await dispatch((0, _sources.ensureParserHasSourceText)(sourceId));
-
-  return await (0, _pause.updateScopeBindings)(scopes, generatedLocation, sourceMaps);
-}
-
-/**
- * Redux actions for the pause state
- * @module actions/pause
- */
-
-/**
- * Debugger has just resumed
- *
- * @memberof actions/pause
- * @static
- */
-function resumed() {
-  return ({ dispatch, client, getState }) => {
-    if (!(0, _selectors.isPaused)(getState())) {
-      return;
-    }
-
-    const wasPausedInEval = (0, _selectors.pausedInEval)(getState());
-
-    dispatch({
-      type: "RESUME",
-      value: undefined
-    });
-
-    if (!(0, _selectors.isStepping)(getState()) && !wasPausedInEval) {
-      dispatch((0, _expressions.evaluateExpressions)());
-    }
-  };
-}
-
-function continueToHere(line) {
-  return async function ({ dispatch, getState, client, sourceMaps }) {
-    const source = (0, _selectors.getSelectedSource)(getState()).toJS();
-
-    await dispatch((0, _breakpoints.addHiddenBreakpoint)({
-      line,
-      column: undefined,
-      sourceId: source.id
-    }));
-
-    dispatch(command("resume"));
-  };
-}
-
-/**
- * Debugger has just paused
- *
- * @param {object} pauseInfo
- * @memberof actions/pause
- * @static
- */
-function paused(pauseInfo) {
-  return async function ({ dispatch, getState, client, sourceMaps }) {
-    let { frames, why, loadedObjects } = pauseInfo;
-
-    frames = await (0, _pause.updateFrameLocations)(frames, sourceMaps);
-    const frame = frames[0];
-
-    const frameScopes = await client.getFrameScopes(frame);
-    const scopes = !(0, _devtoolsSourceMap.isGeneratedId)(frame.location.sourceId) ? await _getScopeBindings({ dispatch, getState, sourceMaps }, frame.generatedLocation, frameScopes) : frameScopes;
-
-    dispatch({
-      type: "PAUSED",
-      pauseInfo: { why, frame, frames },
-      frames: frames,
-      scopes,
-      selectedFrameId: frame.id,
-      loadedObjects: loadedObjects || []
-    });
-
-    const hiddenBreakpointLocation = (0, _breakpoints2.getHiddenBreakpointLocation)(getState());
-    if (hiddenBreakpointLocation) {
-      dispatch((0, _breakpoints.removeBreakpoint)(hiddenBreakpointLocation));
-    }
-
-    if (!(0, _selectors.isEvaluatingExpression)(getState())) {
-      dispatch((0, _expressions.evaluateExpressions)());
-    }
-
-    dispatch((0, _sources.selectSource)(frame.location.sourceId, { line: frame.location.line }));
-  };
-}
-
-/**
- *
- * @memberof actions/pause
- * @static
- */
-function pauseOnExceptions(shouldPauseOnExceptions, shouldIgnoreCaughtExceptions) {
-  return ({ dispatch, client }) => {
-    dispatch({
-      type: "PAUSE_ON_EXCEPTIONS",
-      shouldPauseOnExceptions,
-      shouldIgnoreCaughtExceptions,
-      [_promise.PROMISE]: client.pauseOnExceptions(shouldPauseOnExceptions, shouldIgnoreCaughtExceptions)
-    });
-  };
-}
-
-/**
- * Debugger commands like stepOver, stepIn, stepUp
- *
- * @param string $0.type
- * @memberof actions/pause
- * @static
- */
-function command(type) {
-  return async ({ dispatch, client }) => {
-    // execute debugger thread command e.g. stepIn, stepOver
-    dispatch({ type: "COMMAND", value: { type } });
-
-    await client[type]();
-
-    dispatch({ type: "CLEAR_COMMAND" });
-  };
-}
-
-/**
- * StepIn
- * @memberof actions/pause
- * @static
- * @returns {Function} {@link command}
- */
-function stepIn() {
-  return ({ dispatch, getState }) => {
-    if ((0, _selectors.getPause)(getState())) {
-      return dispatch(command("stepIn"));
-    }
-  };
-}
-
-/**
- * stepOver
- * @memberof actions/pause
- * @static
- * @returns {Function} {@link command}
- */
-function stepOver() {
-  return ({ dispatch, getState }) => {
-    if ((0, _selectors.getPause)(getState())) {
-      return dispatch(astCommand("stepOver"));
-    }
-  };
-}
-
-/**
- * stepOut
- * @memberof actions/pause
- * @static
- * @returns {Function} {@link command}
- */
-function stepOut() {
-  return ({ dispatch, getState }) => {
-    if ((0, _selectors.getPause)(getState())) {
-      return dispatch(command("stepOut"));
-    }
-  };
-}
-
-/**
- * resume
- * @memberof actions/pause
- * @static
- * @returns {Function} {@link command}
- */
-function resume() {
-  return ({ dispatch, getState }) => {
-    if ((0, _selectors.getPause)(getState())) {
-      return dispatch(command("resume"));
-    }
-  };
-}
-
-/**
- * Debugger breakOnNext command.
- * It's different from the comand action because we also want to
- * highlight the pause icon.
- *
- * @memberof actions/pause
- * @static
- */
-function breakOnNext() {
-  return ({ dispatch, client }) => {
-    client.breakOnNext();
-
-    return dispatch({
-      type: "BREAK_ON_NEXT",
-      value: true
-    });
-  };
-}
-
-/**
- * @memberof actions/pause
- * @static
- */
-function selectFrame(frame) {
-  return async ({ dispatch, client, getState, sourceMaps }) => {
-    const frameScopes = await client.getFrameScopes(frame);
-    const scopes = !(0, _devtoolsSourceMap.isGeneratedId)(frame.location.sourceId) ? await _getScopeBindings({ dispatch, getState, sourceMaps }, frame.generatedLocation, frameScopes) : frameScopes;
-
-    dispatch({
-      type: "SELECT_FRAME",
-      frame,
-      scopes
-    });
-
-    dispatch((0, _sources.selectSource)(frame.location.sourceId, { line: frame.location.line }));
-
-    dispatch((0, _expressions.evaluateExpressions)());
-  };
-}
-
-/**
- * @memberof actions/pause
- * @static
- */
-function loadObjectProperties(object) {
-  return ({ dispatch, client, getState }) => {
-    const objectId = object.actor || object.objectId;
-
-    if ((0, _selectors.getLoadedObject)(getState(), objectId)) {
-      return;
-    }
-
-    dispatch({
-      type: "LOAD_OBJECT_PROPERTIES",
-      objectId,
-      [_promise.PROMISE]: client.getProperties(object)
-    });
-  };
-}
-
-/**
- * @memberOf actions/pause
- * @static
- * @param stepType
- * @returns {function(ThunkArgs)}
- */
-function astCommand(stepType) {
-  return async ({ dispatch, getState, sourceMaps }) => {
-    if (!_prefs.features.asyncStepping) {
-      return dispatch(command(stepType));
-    }
-
-    const pauseInfo = (0, _selectors.getPause)(getState());
-    const source = (0, _selectors.getSelectedSource)(getState()).toJS();
-
-    const pausedPosition = await (0, _pause.getPausedPosition)(pauseInfo, sourceMaps);
-
-    if (stepType == "stepOver") {
-      const nextLocation = await parser.getNextStep(source, pausedPosition);
-      if (nextLocation) {
-        await dispatch((0, _breakpoints.addHiddenBreakpoint)(nextLocation));
-        return dispatch(command("resume"));
-      }
-    }
-
-    return dispatch(command(stepType));
-  };
-}
-
-/***/ }),
+/* 1528 */,
 /* 1529 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -33761,17 +33286,16 @@ var _classnames2 = _interopRequireDefaul
 
 var _text = __webpack_require__(1387);
 
 __webpack_require__(1304);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class ShortcutsModal extends _react.Component {
-
   renderPrettyCombos(combo) {
     return combo.split(" ").map(c => _react2.default.createElement(
       "span",
       { key: c, className: "keystroke" },
       c
     )).reduce((prev, curr) => [prev, " + ", curr]);
   }
 
@@ -33881,37 +33405,32 @@ class ShortcutsModal extends _react.Comp
   }
 }
 exports.ShortcutsModal = ShortcutsModal;
 
 /***/ }),
 /* 1536 */
 /***/ (function(module, exports, __webpack_require__) {
 
-"use strict";
-
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var React = __webpack_require__(0);
-var ReactDOM = __webpack_require__(4);
-var Draggable = React.createFactory(__webpack_require__(1537));
-var dom = React.DOM,
-    PropTypes = React.PropTypes;
-
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const React = __webpack_require__(0);
+const ReactDOM = __webpack_require__(4);
+const Draggable = React.createFactory(__webpack_require__(1537));
+const { DOM: dom, PropTypes } = React;
 
 __webpack_require__(1309);
 
 /**
  * This component represents a Splitter. The splitter supports vertical
  * as well as horizontal mode.
  */
-var SplitBox = React.createClass({
+const SplitBox = React.createClass({
   propTypes: {
     // Custom class name. You can use more names separated by a space.
     className: PropTypes.string,
     // Initial size of controlled panel.
     initialSize: PropTypes.any,
     // Optional initial width of controlled panel.
     initialWidth: PropTypes.number,
     // Optional initial height of controlled panel.
@@ -33937,196 +33456,183 @@ var SplitBox = React.createClass({
     // Optional style properties passed into the splitbox
     style: PropTypes.object,
     // Optional callback when splitbox resize stops
     onResizeEnd: PropTypes.func
   },
 
   displayName: "SplitBox",
 
-  getDefaultProps: function getDefaultProps() {
+  getDefaultProps() {
     return {
       splitterSize: 5,
       vert: true,
       endPanelControl: false,
       endPanelCollapsed: false,
       startPanelCollapsed: false
     };
   },
 
-
   /**
    * The state stores the current orientation (vertical or horizontal)
    * and the current size (width/height). All these values can change
    * during the component's life time.
    */
-  getInitialState: function getInitialState() {
+  getInitialState() {
     return {
       vert: this.props.vert,
       // We use integers for these properties
       width: parseInt(this.props.initialWidth || this.props.initialSize),
       height: parseInt(this.props.initialHeight || this.props.initialSize)
     };
   },
-  componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
+
+  componentWillReceiveProps(nextProps) {
     if (this.props.vert !== nextProps.vert) {
       this.setState({ vert: nextProps.vert });
     }
   },
 
-
   // Dragging Events
 
   /**
    * Set 'resizing' cursor on entire document during splitter dragging.
    * This avoids cursor-flickering that happens when the mouse leaves
    * the splitter bar area (happens frequently).
    */
-  onStartMove: function onStartMove() {
-    var splitBox = ReactDOM.findDOMNode(this);
-    var doc = splitBox.ownerDocument;
-    var defaultCursor = doc.documentElement.style.cursor;
+  onStartMove() {
+    const splitBox = ReactDOM.findDOMNode(this);
+    const doc = splitBox.ownerDocument;
+    let defaultCursor = doc.documentElement.style.cursor;
     doc.documentElement.style.cursor = this.state.vert ? "ew-resize" : "ns-resize";
 
     splitBox.classList.add("dragging");
 
     this.setState({
       defaultCursor: defaultCursor
     });
   },
-  onStopMove: function onStopMove() {
-    var splitBox = ReactDOM.findDOMNode(this);
-    var doc = splitBox.ownerDocument;
+
+  onStopMove() {
+    const splitBox = ReactDOM.findDOMNode(this);
+    const doc = splitBox.ownerDocument;
     doc.documentElement.style.cursor = this.state.defaultCursor;
 
     splitBox.classList.remove("dragging");
 
     if (this.props.onResizeEnd) {
       this.props.onResizeEnd(this.state.vert ? this.state.width : this.state.height);
     }
   },
 
-
   /**
    * Adjust size of the controlled panel. Depending on the current
    * orientation we either remember the width or height of
    * the splitter box.
    */
-  onMove: function onMove(_ref) {
-    var movementX = _ref.movementX,
-        movementY = _ref.movementY;
-
-    var node = ReactDOM.findDOMNode(this);
-    var doc = node.ownerDocument;
+  onMove({ movementX, movementY }) {
+    const node = ReactDOM.findDOMNode(this);
+    const doc = node.ownerDocument;
 
     if (this.props.endPanelControl) {
       // For the end panel we need to increase the width/height when the
       // movement is towards the left/top.
       movementX = -movementX;
       movementY = -movementY;
     }
 
     if (this.state.vert) {
-      var isRtl = doc.dir === "rtl";
+      const isRtl = doc.dir === "rtl";
       if (isRtl) {
         // In RTL we need to reverse the movement again -- but only for vertical
         // splitters
         movementX = -movementX;
       }
 
-      this.setState(function (state, props) {
-        return {
-          width: state.width + movementX
-        };
-      });
-    } else {
-      this.setState(function (state, props) {
-        return {
-          height: state.height + movementY
-        };
-      });
-    }
-  },
-
+      this.setState((state, props) => ({
+        width: state.width + movementX
+      }));
+    } else {
+      this.setState((state, props) => ({
+        height: state.height + movementY
+      }));
+    }
+  },
 
   // Rendering
-  preparePanelStyles: function preparePanelStyles() {
-    var vert = this.state.vert;
-    var _props = this.props,
-        minSize = _props.minSize,
-        maxSize = _props.maxSize,
-        startPanelCollapsed = _props.startPanelCollapsed,
-        endPanelControl = _props.endPanelControl,
-        endPanelCollapsed = _props.endPanelCollapsed;
-
-    var leftPanelStyle = void 0,
-        rightPanelStyle = void 0;
+  preparePanelStyles() {
+    const vert = this.state.vert;
+    const {
+      minSize,
+      maxSize,
+      startPanelCollapsed,
+      endPanelControl,
+      endPanelCollapsed
+    } = this.props;
+    let leftPanelStyle, rightPanelStyle;
 
     // Set proper size for panels depending on the current state.
     if (vert) {
-      var startWidth = endPanelControl ? null : this.state.width,
+      let startWidth = endPanelControl ? null : this.state.width,
           endWidth = endPanelControl ? this.state.width : null;
 
       leftPanelStyle = {
         maxWidth: endPanelControl ? null : maxSize,
         minWidth: endPanelControl ? null : minSize,
         width: startPanelCollapsed ? 0 : startWidth
       };
       rightPanelStyle = {
         maxWidth: endPanelControl ? maxSize : null,
         minWidth: endPanelControl ? minSize : null,
         width: endPanelCollapsed ? 0 : endWidth
       };
     } else {
-      var startHeight = endPanelControl ? null : this.state.height,
+      let startHeight = endPanelControl ? null : this.state.height,
           endHeight = endPanelControl ? this.state.height : null;
 
       leftPanelStyle = {
         maxHeight: endPanelControl ? null : maxSize,
         minHeight: endPanelControl ? null : minSize,
         height: endPanelCollapsed ? maxSize : startHeight
       };
       rightPanelStyle = {
         maxHeight: endPanelControl ? maxSize : null,
         minHeight: endPanelControl ? minSize : null,
         height: startPanelCollapsed ? maxSize : endHeight
       };
     }
 
-    return { leftPanelStyle: leftPanelStyle, rightPanelStyle: rightPanelStyle };
-  },
-  render: function render() {
-    var vert = this.state.vert;
-    var _props2 = this.props,
-        startPanelCollapsed = _props2.startPanelCollapsed,
-        startPanel = _props2.startPanel,
-        endPanel = _props2.endPanel,
-        endPanelControl = _props2.endPanelControl,
-        splitterSize = _props2.splitterSize,
-        endPanelCollapsed = _props2.endPanelCollapsed;
-
-
-    var style = Object.assign({}, this.props.style);
+    return { leftPanelStyle, rightPanelStyle };
+  },
+
+  render() {
+    const vert = this.state.vert;
+    const {
+      startPanelCollapsed,
+      startPanel,
+      endPanel,
+      endPanelControl,
+      splitterSize,
+      endPanelCollapsed
+    } = this.props;
+
+    let style = Object.assign({}, this.props.style);
 
     // Calculate class names list.
-    var classNames = ["split-box"];
+    let classNames = ["split-box"];
     classNames.push(vert ? "vert" : "horz");
     if (this.props.className) {
       classNames = classNames.concat(this.props.className.split(" "));
     }
 
-    var _preparePanelStyles = this.preparePanelStyles(),
-        leftPanelStyle = _preparePanelStyles.leftPanelStyle,
-        rightPanelStyle = _preparePanelStyles.rightPanelStyle;
+    const { leftPanelStyle, rightPanelStyle } = this.preparePanelStyles();
 
     // Calculate splitter size
-
-
-    var splitterStyle = {
-      flex: "0 0 " + splitterSize + "px"
+    let splitterStyle = {
+      flex: `0 0 ${splitterSize}px`
     };
 
     return dom.div({
       className: classNames.join(" "),
       style: style
     }, !startPanelCollapsed ? dom.div({
       className: endPanelControl ? "uncontrolled" : "controlled",
       style: leftPanelStyle
@@ -34144,61 +33650,59 @@ var SplitBox = React.createClass({
 });
 
 module.exports = SplitBox;
 
 /***/ }),
 /* 1537 */
 /***/ (function(module, exports, __webpack_require__) {
 
-"use strict";
-
-
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-var React = __webpack_require__(0);
-var ReactDOM = __webpack_require__(4);
-var dom = React.DOM,
-    PropTypes = React.PropTypes;
-
-
-var Draggable = React.createClass({
+const React = __webpack_require__(0);
+const ReactDOM = __webpack_require__(4);
+const { DOM: dom, PropTypes } = React;
+
+const Draggable = React.createClass({
   displayName: "Draggable",
 
   propTypes: {
     onMove: PropTypes.func.isRequired,
     onStart: PropTypes.func,
     onStop: PropTypes.func,
     style: PropTypes.object,
     className: PropTypes.string
   },
 
-  startDragging: function startDragging(ev) {
+  startDragging(ev) {
     ev.preventDefault();
-    var doc = ReactDOM.findDOMNode(this).ownerDocument;
+    const doc = ReactDOM.findDOMNode(this).ownerDocument;
     doc.addEventListener("mousemove", this.onMove);
     doc.addEventListener("mouseup", this.onUp);
     this.props.onStart && this.props.onStart();
   },
-  onMove: function onMove(ev) {
+
+  onMove(ev) {
     ev.preventDefault();
     // We pass the whole event because we don't know which properties
     // the callee needs.
     this.props.onMove(ev);
   },
-  onUp: function onUp(ev) {
+
+  onUp(ev) {
     ev.preventDefault();
-    var doc = ReactDOM.findDOMNode(this).ownerDocument;
+    const doc = ReactDOM.findDOMNode(this).ownerDocument;
     doc.removeEventListener("mousemove", this.onMove);
     doc.removeEventListener("mouseup", this.onUp);
     this.props.onStop && this.props.onStop();
   },
-  render: function render() {
+
+  render() {
     return dom.div({
       style: this.props.style,
       className: this.props.className,
       onMouseDown: this.startDragging
     });
   }
 });
 
@@ -34230,166 +33734,109 @@ var _redux = __webpack_require__(3);
 var _actions = __webpack_require__(1354);
 
 var _actions2 = _interopRequireDefault(_actions);
 
 var _TextSearch = __webpack_require__(1539);
 
 var _TextSearch2 = _interopRequireDefault(_TextSearch);
 
-var _SourceSearch = __webpack_require__(1548);
-
-var _SourceSearch2 = _interopRequireDefault(_SourceSearch);
-
-var _ToggleSearch = __webpack_require__(1550);
-
-var _ToggleSearch2 = _interopRequireDefault(_ToggleSearch);
-
 var _selectors = __webpack_require__(1352);
 
 __webpack_require__(1317);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class ProjectSearch extends _react.Component {
 
   constructor(props) {
     super(props);
-
-    this.toggleSourceSearch = this.toggleSourceSearch.bind(this);
     this.toggleProjectTextSearch = this.toggleProjectTextSearch.bind(this);
   }
 
   componentDidMount() {
     const shortcuts = this.context.shortcuts;
 
     shortcuts.on(L10N.getStr("projectTextSearch.key"), this.toggleProjectTextSearch);
-
-    const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")];
-    searchKeys.forEach(key => shortcuts.on(key, this.toggleSourceSearch));
   }
 
   componentWillUnmount() {
     const shortcuts = this.context.shortcuts;
     shortcuts.off(L10N.getStr("projectTextSearch.key"), this.toggleProjectTextSearch);
-
-    const searchKeys = [L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key")];
-    searchKeys.forEach(key => shortcuts.off(key, this.toggleSourceSearch));
   }
 
   toggleProjectTextSearch(key, e) {
     const { closeActiveSearch, setActiveSearch } = this.props;
     if (e) {
       e.preventDefault();
     }
 
     if (this.isProjectSearchEnabled()) {
       return closeActiveSearch();
     }
     return setActiveSearch("project");
   }
 
-  toggleSourceSearch(key, e) {
-    const { closeActiveSearch, setActiveSearch } = this.props;
-    if (e) {
-      e.preventDefault();
-    }
-
-    if (this.isSourceSearchEnabled()) {
-      return closeActiveSearch();
-    }
-    return setActiveSearch("source");
-  }
-
   isProjectSearchEnabled() {
     return this.props.activeSearch === "project";
   }
 
-  isSourceSearchEnabled() {
-    return this.props.activeSearch === "source";
-  }
-
-  renderSourceSearch() {
-    const {
-      sources,
-      selectSource,
-      closeActiveSearch,
-      sourceSearchQuery,
-      setSourceSearchQuery,
-      clearSourceSearchQuery
-    } = this.props;
-    return _react2.default.createElement(_SourceSearch2.default, {
-      sources: sources,
-      selectSource: selectSource,
-      closeActiveSearch: closeActiveSearch,
-      searchBottomBar: _react2.default.createElement(_ToggleSearch2.default, { kind: "sources", toggle: this.toggleProjectTextSearch }),
-      query: sourceSearchQuery,
-      setQuery: setSourceSearchQuery,
-      clearQuery: clearSourceSearchQuery
-    });
-  }
-
   renderTextSearch() {
     const {
       sources,
       results,
       searchSources,
       closeActiveSearch,
       selectSource,
       textSearchQuery
     } = this.props;
 
     return _react2.default.createElement(_TextSearch2.default, {
       sources: sources,
       results: results.toJS(),
       searchSources: searchSources,
       closeActiveSearch: closeActiveSearch,
       selectSource: selectSource,
-      query: textSearchQuery,
-      searchBottomBar: _react2.default.createElement(_ToggleSearch2.default, { kind: "project", toggle: this.toggleSourceSearch })
-    });
-  }
-
-  render() {
-    if (!(this.isProjectSearchEnabled() || this.isSourceSearchEnabled())) {
+      query: textSearchQuery
+    });
+  }
+
+  render() {
+    if (!this.isProjectSearchEnabled()) {
       return null;
     }
 
     return _react2.default.createElement(
       "div",
       { className: "search-container" },
-      this.isProjectSearchEnabled() ? this.renderTextSearch() : this.renderSourceSearch()
+      this.renderTextSearch()
     );
   }
 }
 
 ProjectSearch.propTypes = {
   sources: _propTypes2.default.object.isRequired,
   results: _propTypes2.default.object,
   textSearchQuery: _propTypes2.default.string,
   setActiveSearch: _propTypes2.default.func.isRequired,
   closeActiveSearch: _propTypes2.default.func.isRequired,
   searchSources: _propTypes2.default.func,
   activeSearch: _propTypes2.default.string,
-  selectSource: _propTypes2.default.func.isRequired,
-  sourceSearchQuery: _propTypes2.default.string,
-  setSourceSearchQuery: _propTypes2.default.func,
-  clearSourceSearchQuery: _propTypes2.default.func
+  selectSource: _propTypes2.default.func.isRequired
 };
 
 ProjectSearch.contextTypes = {
   shortcuts: _propTypes2.default.object
 };
 
 exports.default = (0, _reactRedux.connect)(state => ({
   sources: (0, _selectors.getSources)(state),
   activeSearch: (0, _selectors.getActiveSearch)(state),
   results: (0, _selectors.getTextSearchResults)(state),
-  textSearchQuery: (0, _selectors.getTextSearchQuery)(state),
-  sourceSearchQuery: (0, _selectors.getSourceSearchQuery)(state)
+  textSearchQuery: (0, _selectors.getTextSearchQuery)(state)
 }), dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(ProjectSearch);
 
 /***/ }),
 /* 1539 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -34452,17 +33899,18 @@ class TextSearch extends _react.Componen
   }
 
   componentWillUnmount() {
     const shortcuts = this.context.shortcuts;
     shortcuts.off("Enter", this.onEnterPress);
   }
 
   selectMatchItem(matchItem) {
-    this.props.selectSource(matchItem.sourceId, { line: matchItem.line });
+    const { line, column } = matchItem;
+    this.props.selectSource(matchItem.sourceId, { location: { line, column } });
   }
 
   getResults() {
     const { results } = this.props;
     return results.filter(result => result.filepath && result.matches.length > 0);
   }
 
   getResultCount() {
@@ -34511,17 +33959,17 @@ class TextSearch extends _react.Componen
     return _react2.default.createElement(
       "div",
       {
         className: (0, _classnames2.default)("file-result", { focused }),
         key: file.sourceId,
         onClick: e => setExpanded(file, !expanded)
       },
       _react2.default.createElement(_Svg2.default, { name: "arrow", className: (0, _classnames2.default)({ expanded }) }),
-      _react2.default.createElement(_Svg2.default, { name: "file" }),
+      _react2.default.createElement("img", { className: "file" }),
       _react2.default.createElement(
         "span",
         { className: "file-path" },
         (0, _sourcesTree.getRelativePath)(file.filepath)
       ),
       _react2.default.createElement(
         "span",
         { className: "matches-summary" },
@@ -34667,16 +34115,17 @@ const svg = {
   vuejs: __webpack_require__(1174),
   "magnifying-glass": __webpack_require__(357),
   "arrow-up": __webpack_require__(919),
   "arrow-down": __webpack_require__(920),
   pause: __webpack_require__(358),
   "pause-exceptions": __webpack_require__(359),
   plus: __webpack_require__(360),
   preact: __webpack_require__(1233),
+  aframe: __webpack_require__(1648),
   prettyPrint: __webpack_require__(361),
   react: __webpack_require__(1000),
   "regex-match": __webpack_require__(362),
   redux: __webpack_require__(256),
   immutable: __webpack_require__(258),
   resume: __webpack_require__(363),
   settings: __webpack_require__(364),
   stepIn: __webpack_require__(365),
@@ -34689,18 +34138,21 @@ const svg = {
   worker: __webpack_require__(372),
   "sad-face": __webpack_require__(1347),
   refresh: __webpack_require__(1348),
   webpack: __webpack_require__(1001),
   node: __webpack_require__(1002),
   express: __webpack_require__(1003),
   pug: __webpack_require__(1004),
   extjs: __webpack_require__(1043),
+  marko: __webpack_require__(1649),
+  nextjs: __webpack_require__(1650),
   showSources: __webpack_require__(1044),
-  showOutline: __webpack_require__(1045)
+  showOutline: __webpack_require__(1045),
+  nuxtjs: __webpack_require__(1651)
 };
 
 function Svg({ name, className, onClick, "aria-label": ariaLabel }) {
   if (!svg[name]) {
     const error = `Unknown SVG: ${name}`;
     if (isDevelopment()) {
       throw new Error(error);
     }
@@ -35631,301 +35083,19 @@ function highlightMatches(lineMatch) {
       "span",
       { className: "line-match", key: 2 },
       value.slice(column + len, value.length)
     )
   );
 } // Maybe reuse file search's functions?
 
 /***/ }),
-/* 1548 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-
-var _propTypes = __webpack_require__(20);
-
-var _propTypes2 = _interopRequireDefault(_propTypes);
-
-var _react = __webpack_require__(0);
-
-var _react2 = _interopRequireDefault(_react);
-
-var _source = __webpack_require__(1356);
-
-var _utils = __webpack_require__(1366);
-
-var _Autocomplete = __webpack_require__(1549);
-
-var _Autocomplete2 = _interopRequireDefault(_Autocomplete);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-class SourceSearch extends _react.Component {
-
-  searchResults(sources) {
-    return sources.valueSeq().toJS().filter(source => !(0, _source.isPretty)(source) && !(0, _source.isThirdParty)(source)).map(source => ({
-      value: (0, _source.getSourcePath)(source),
-      title: (0, _source.getSourcePath)(source).split("/").pop(),
-      subtitle: (0, _utils.endTruncateStr)((0, _source.getSourcePath)(source), 100),
-      id: source.id
-    }));
-  }
-
-  render() {
-    const {
-      sources,
-      searchBottomBar,
-      selectSource,
-      query,
-      setQuery
-    } = this.props;
-    return _react2.default.createElement(
-      _Autocomplete2.default,
-      {
-        selectItem: (e, result) => selectSource(result.id),
-        close: this.props.closeActiveSearch,
-        items: this.searchResults(sources),
-        inputValue: query,
-        placeholder: L10N.getStr("sourceSearch.search"),
-        onChangeHandler: setQuery,
-        size: "big"
-      },
-      searchBottomBar
-    );
-  }
-}
-
-exports.default = SourceSearch;
-SourceSearch.contextTypes = {
-  shortcuts: _propTypes2.default.object
-};
-
-/***/ }),
-/* 1549 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-
-var _react = __webpack_require__(0);
-
-var _react2 = _interopRequireDefault(_react);
-
-var _fuzzaldrinPlus = __webpack_require__(161);
-
-var _classnames = __webpack_require__(175);
-
-var _classnames2 = _interopRequireDefault(_classnames);
-
-var _resultList = __webpack_require__(1406);
-
-__webpack_require__(1315);
-
-var _SearchInput = __webpack_require__(1379);
-
-var _SearchInput2 = _interopRequireDefault(_SearchInput);
-
-var _ResultList = __webpack_require__(1445);
-
-var _ResultList2 = _interopRequireDefault(_ResultList);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-class Autocomplete extends _react.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.onKeyDown = this.onKeyDown.bind(this);
-    this.state = {
-      selectedIndex: 0,
-      focused: false
-    };
-  }
-
-  componentDidUpdate() {
-    if (this.refs.resultList && this.refs.resultList.refs) {
-      (0, _resultList.scrollList)(this.refs.resultList.refs, this.state.selectedIndex);
-    }
-  }
-
-  getSearchResults() {
-    const inputValue = this.props.inputValue;
-    if (inputValue == "") {
-      return [];
-    }
-
-    return (0, _fuzzaldrinPlus.filter)(this.props.items, inputValue, {
-      key: "value"
-    });
-  }
-
-  onKeyDown(e) {
-    const searchResults = this.getSearchResults(),
-          resultCount = searchResults.length;
-
-    if (e.key === "ArrowUp") {
-      const selectedIndex = Math.max(0, this.state.selectedIndex - 1);
-      this.setState({ selectedIndex });
-      if (this.props.onSelectedItem) {
-        this.props.onSelectedItem(searchResults[selectedIndex]);
-      }
-      e.preventDefault();
-    } else if (e.key === "ArrowDown") {
-      const selectedIndex = Math.min(resultCount - 1, this.state.selectedIndex + 1);
-      this.setState({ selectedIndex });
-      if (this.props.onSelectedItem) {
-        this.props.onSelectedItem(searchResults[selectedIndex]);
-      }
-      e.preventDefault();
-    } else if (e.key === "Enter") {
-      if (searchResults.length) {
-        this.props.selectItem(e, searchResults[this.state.selectedIndex]);
-      } else {
-        this.props.close(this.props.inputValue);
-      }
-      e.preventDefault();
-    } else if (e.key === "Tab") {
-      this.props.close(this.props.inputValue);
-      e.preventDefault();
-    }
-  }
-
-  renderResults(results) {
-    const { size } = this.props;
-
-    if (results.length) {
-      const props = {
-        items: results,
-        selected: this.state.selectedIndex,
-        selectItem: this.props.selectItem,
-        close: this.props.close,
-        size,
-        ref: "resultList"
-      };
-
-      return _react2.default.createElement(_ResultList2.default, props);
-    } else if (this.props.inputValue && !results.length) {
-      return _react2.default.createElement(
-        "div",
-        { className: "no-result-msg absolute-center" },
-        L10N.getStr("sourceSearch.noResults2")
-      );
-    }
-  }
-
-  render() {
-    const { focused } = this.state;
-    const { size, children } = this.props;
-    const searchResults = this.getSearchResults();
-    const summaryMsg = L10N.getFormatStr("sourceSearch.resultsSummary1", searchResults.length);
-
-    const searchProps = {
-      query: this.props.inputValue,
-      count: searchResults.length,
-      placeholder: this.props.placeholder,
-      size,
-      showErrorEmoji: true,
-      summaryMsg,
-      onChange: e => {
-        this.props.onChangeHandler(e.target.value);
-        this.setState({
-          selectedIndex: 0
-        });
-      },
-      onFocus: () => this.setState({ focused: true }),
-      onBlur: () => this.setState({ focused: false }),
-      onKeyDown: this.onKeyDown,
-      handleClose: this.props.close
-    };
-
-    return _react2.default.createElement(
-      "div",
-      { className: (0, _classnames2.default)("autocomplete", { focused }) },
-      _react2.default.createElement(_SearchInput2.default, searchProps),
-      children,
-      this.renderResults(searchResults)
-    );
-  }
-}
-
-exports.default = Autocomplete;
-Autocomplete.defaultProps = {
-  size: ""
-};
-
-/***/ }),
-/* 1550 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-
-var _propTypes = __webpack_require__(20);
-
-var _propTypes2 = _interopRequireDefault(_propTypes);
-
-var _react = __webpack_require__(0);
-
-var _react2 = _interopRequireDefault(_react);
-
-var _classnames = __webpack_require__(175);
-
-var _classnames2 = _interopRequireDefault(_classnames);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-class ToggleSearch extends _react.Component {
-  render() {
-    const { kind, toggle } = this.props;
-    const isSourcesActive = kind === "sources";
-    return _react2.default.createElement(
-      "div",
-      { className: "toggle-search" },
-      _react2.default.createElement(
-        "span",
-        {
-          className: (0, _classnames2.default)("text", { active: isSourcesActive }),
-          onClick: toggle
-        },
-        L10N.getStr("sourceSearch.search")
-      ),
-      _react2.default.createElement(
-        "span",
-        {
-          className: (0, _classnames2.default)("text", { active: !isSourcesActive }),
-          onClick: toggle
-        },
-        L10N.getStr("projectTextSearch.placeholder")
-      )
-    );
-  }
-}
-
-exports.default = ToggleSearch;
-ToggleSearch.propTypes = {
-  kind: _propTypes2.default.string.isRequired,
-  toggle: _propTypes2.default.func.isRequired
-};
-
-/***/ }),
+/* 1548 */,
+/* 1549 */,
+/* 1550 */,
 /* 1551 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -36098,17 +35268,16 @@ var _PreviewFunction = __webpack_require
 
 var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction);
 
 var _lodash = __webpack_require__(2);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class Outline extends _react.Component {
-
   selectItem(location) {
     const { selectedSource, selectSource } = this.props;
     if (!selectedSource) {
       return;
     }
     const selectedSourceId = selectedSource.get("id");
     const startLine = location.start.line;
     selectSource(selectedSourceId, { line: startLine });
@@ -36252,16 +35421,17 @@ function _interopRequireDefault(obj) { r
 
 class SourcesTree extends _react.Component {
 
   constructor(props) {
     super(props);
     this.state = (0, _sourcesTree.createTree)(this.props.sources, this.props.debuggeeUrl, this.props.projectRoot);
     this.focusItem = this.focusItem.bind(this);
     this.selectItem = this.selectItem.bind(this);
+    this.getPath = this.getPath.bind(this);
     this.getIcon = this.getIcon.bind(this);
     this.onContextMenu = this.onContextMenu.bind(this);
     this.renderItem = this.renderItem.bind(this);
 
     this.queueUpdate = (0, _utils.throttle)(function () {
       if (!this.mounted) {
         return;
       }
@@ -36348,30 +35518,40 @@ class SourcesTree extends _react.Compone
   }
 
   selectItem(item) {
     if (!(0, _sourcesTree.nodeHasChildren)(item)) {
       this.props.selectSource(item.contents.get("id"));
     }
   }
 
-  getIcon(item, depth) {
+  getPath(item) {
+    const { sources } = this.props;
+    const blackBoxedPart = item.contents.get && sources.get(item.contents.get("id")).get("isBlackBoxed") ? "update" : "";
+    return `${item.path}/${item.name}/${blackBoxedPart}`;
+  }
+
+  getIcon(sources, item, depth) {
     if (item.path === "/Webpack") {
       return _react2.default.createElement(_Svg2.default, { name: "webpack" });
     }
 
     if (depth === 0) {
-      return _react2.default.createElement(_Svg2.default, { name: "domain" });
+      return _react2.default.createElement("img", { className: "domain" });
     }
 
     if (!(0, _sourcesTree.nodeHasChildren)(item)) {
-      return _react2.default.createElement(_Svg2.default, { name: "file" });
-    }
-
-    return _react2.default.createElement(_Svg2.default, { name: "folder" });
+      const source = sources.get(item.contents.get("id"));
+      if (source.get("isBlackBoxed")) {
+        return _react2.default.createElement("img", { className: "blackBox" });
+      }
+      return _react2.default.createElement("img", { className: "file" });
+    }
+
+    return _react2.default.createElement("img", { className: "folder" });
   }
 
   onContextMenu(event, item) {
     const copySourceUri2Label = L10N.getStr("copySourceUri2");
     const copySourceUri2Key = L10N.getStr("copySourceUri2.accesskey");
     const setDirectoryRootLabel = L10N.getStr("setDirectoryRoot.label");
     const setDirectoryRootKey = L10N.getStr("setDirectoryRoot.accesskey");
 
@@ -36408,18 +35588,18 @@ class SourcesTree extends _react.Compone
       className: (0, _classnames2.default)("arrow", {
         expanded: expanded
       }),
       onClick: e => {
         e.stopPropagation();
         setExpanded(item, !expanded, e.altKey);
       }
     }) : _react2.default.createElement("i", { className: "no-arrow" });
-
-    const icon = this.getIcon(item, depth);
+    const { sources } = this.props;
+    const icon = this.getIcon(sources, item, depth);
     let paddingDir = "paddingRight";
     if (document.body && document.body.parentElement) {
       paddingDir = document.body.parentElement.dir == "ltr" ? "paddingLeft" : "paddingRight";
     }
 
     return _react2.default.createElement(
       "div",
       {
@@ -36455,17 +35635,17 @@ class SourcesTree extends _react.Compone
     } = this.state;
 
     const isEmpty = sourceTree.contents.length === 0;
     const treeProps = {
       key: isEmpty ? "empty" : "full",
       getParent: item => parentMap.get(item),
       getChildren: item => (0, _sourcesTree.nodeHasChildren)(item) ? item.contents : [],
       getRoots: () => sourceTree.contents,
-      getPath: item => `${item.path}/${item.name}`,
+      getPath: this.getPath,
       itemHeight: 21,
       autoExpandDepth: expanded ? 0 : 1,
       autoExpandAll: false,
       onFocus: this.focusItem,
       listItems,
       highlightItems,
       expanded,
       onExpand: (item, expandedState) => setExpandedState(expandedState),
@@ -36511,17 +35691,18 @@ class SourcesTree extends _react.Compone
 
 // React
 exports.default = (0, _reactRedux.connect)(state => {
   return {
     shownSource: (0, _selectors.getShownSource)(state),
     selectedSource: (0, _selectors.getSelectedSource)(state),
     debuggeeUrl: (0, _selectors.getDebuggeeUrl)(state),
     expanded: (0, _selectors.getExpandedState)(state),
-    projectRoot: (0, _selectors.getProjectDirectoryRoot)(state)
+    projectRoot: (0, _selectors.getProjectDirectoryRoot)(state),
+    sources: (0, _selectors.getSources)(state)
   };
 }, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(SourcesTree);
 
 /***/ }),
 /* 1554 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -36614,28 +35795,31 @@ var _EditorMenu = __webpack_require__(15
 var _EditorMenu2 = _interopRequireDefault(_EditorMenu);
 
 var _ConditionalPanel = __webpack_require__(1598);
 
 var _ConditionalPanel2 = _interopRequireDefault(_ConditionalPanel);
 
 var _editor = __webpack_require__(1358);
 
+var _ui = __webpack_require__(1439);
+
 __webpack_require__(1332);
 
 __webpack_require__(1333);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 const cssVars = {
   searchbarHeight: "var(--editor-searchbar-height)",
   secondSearchbarHeight: "var(--editor-second-searchbar-height)",
   footerHeight: "var(--editor-footer-height)"
 };
 
+
 class Editor extends _react.PureComponent {
 
   constructor() {
     super();
 
     this.onToggleBreakpoint = (key, e) => {
       e.preventDefault();
       const { codeMirror } = this.state.editor;
@@ -36707,16 +35891,18 @@ class Editor extends _react.PureComponen
 
       if (ev.shiftKey) {
         return addOrToggleDisabledBreakpoint(sourceLine);
       }
       return toggleBreakpoint(sourceLine);
     };
 
     this.onGutterContextMenu = event => {
+      event.stopPropagation();
+      event.preventDefault();
       return this.props.setContextMenu("Gutter", event);
     };
 
     this.toggleConditionalPanel = line => {
       const {
         conditionalPanelLine,
         closeConditionalPanel,
         openConditionalPanel
@@ -36741,17 +35927,18 @@ class Editor extends _react.PureComponen
     };
   }
 
   componentWillReceiveProps(nextProps) {
     if (!this.state.editor) {
       return;
     }
 
-    (0, _editor.resizeBreakpointGutter)(this.state.editor.codeMirror);
+    (0, _ui.resizeBreakpointGutter)(this.state.editor.codeMirror);
+    (0, _ui.resizeToggleButton)(this.state.editor.codeMirror);
   }
 
   setupEditor() {
     const editor = (0, _editor.createEditor)();
 
     // disables the default search shortcuts
 
     editor._initShortcuts = () => {};
@@ -36759,17 +35946,19 @@ class Editor extends _react.PureComponen
     const node = _reactDom2.default.findDOMNode(this);
     if (node instanceof HTMLElement) {
       editor.appendToLocalElement(node.querySelector(".editor-mount"));
     }
 
     const { codeMirror } = editor;
     const codeMirrorWrapper = codeMirror.getWrapperElement();
 
-    (0, _editor.resizeBreakpointGutter)(codeMirror);
+    (0, _ui.resizeBreakpointGutter)(codeMirror);
+    (0, _ui.resizeToggleButton)(codeMirror);
+
     (0, _devtoolsLaunchpad.debugGlobal)("cm", codeMirror);
 
     codeMirror.on("gutterClick", this.onGutterClick);
 
     // Set code editor wrapper to be focusable
     codeMirrorWrapper.tabIndex = 0;
     codeMirrorWrapper.addEventListener("keydown", e => this.onKeyDown(e));
     codeMirrorWrapper.addEventListener("click", e => this.onClick(e));
@@ -36782,29 +35971,20 @@ class Editor extends _react.PureComponen
       }
     };
 
     const codeMirrorGutter = codeMirror.getGutterElement();
     codeMirrorGutter.addEventListener("mouseleave", toggleFoldMarkerVisibility);
     codeMirrorGutter.addEventListener("mouseenter", toggleFoldMarkerVisibility);
 
     if (!(0, _devtoolsConfig.isFirefox)()) {
-      codeMirror.on("gutterContextMenu", (cm, line, eventName, event) => {
-        event.stopPropagation();
-        event.preventDefault();
-        return this.onGutterContextMenu(event);
-      });
-
+      codeMirror.on("gutterContextMenu", (cm, line, eventName, event) => this.onGutterContextMenu(event));
       codeMirror.on("contextmenu", (cm, event) => this.openMenu(event));
     } else {
-      codeMirrorWrapper.addEventListener("contextmenu", event => {
-        event.stopPropagation();
-        event.preventDefault();
-        return this.openMenu(event);
-      });
+      codeMirrorWrapper.addEventListener("contextmenu", event => this.openMenu(event));
     }
 
     this.setState({ editor });
     return editor;
   }
 
   componentDidMount() {
     const editor = this.setupEditor();
@@ -36852,29 +36032,30 @@ class Editor extends _react.PureComponen
     // `this.props` to be the current props. This lifecycle method is
     // responsible for updating the editor annotations.
     const { selectedLocation, selectedSource } = this.props;
 
     // If the location is different and a new line is requested,
     // update the pending jump line. Note that if jumping to a line in
     // a source where the text hasn't been loaded yet, we will set the
     // line here but not jump until rendering the actual source.
+
     if (prevProps.selectedLocation !== selectedLocation) {
       if (selectedLocation && selectedLocation.line != undefined) {
         this.pendingJumpLocation = selectedLocation;
       } else {
         this.pendingJumpLocation = null;
       }
     }
 
     // Only update and jump around in real source texts. This will
     // keep the jump state around until the real source text is
     // loaded.
-    if (selectedSource && selectedSource.has("text")) {
-      this.flashLine();
+    if (selectedSource && (0, _source.isLoaded)(selectedSource.toJS())) {
+      this.highlightLine();
     }
   }
 
   onKeyDown(e) {
     const { codeMirror } = this.state.editor;
     const { key, target } = e;
     const codeWrapper = codeMirror.getWrapperElement();
     const textArea = codeWrapper.querySelector("textArea");
@@ -36894,16 +36075,19 @@ class Editor extends _react.PureComponen
    * The default Esc command is overridden in the CodeMirror keymap to allow
    * the Esc keypress event to be catched by the toolbox and trigger the
    * split console. Restore it here, but preventDefault if and only if there
    * is a multiselection.
    */
 
 
   openMenu(event) {
+    event.stopPropagation();
+    event.preventDefault();
+
     const { setContextMenu } = this.props;
 
     if (event.target.classList.contains("CodeMirror-linenumber")) {
       return setContextMenu("Gutter", event);
     }
 
     return setContextMenu("Editor", event);
   }
@@ -36914,45 +36098,54 @@ class Editor extends _react.PureComponen
     if (e.metaKey && e.altKey) {
       const sourceLocation = (0, _editor.getSourceLocationFromMouseEvent)(this.state.editor, selectedLocation, e);
       jumpToMappedLocation(sourceLocation);
     }
   }
 
   // If the location has changed and a specific line is requested,
   // move to that line and flash it.
-  flashLine() {
-    if (!this.pendingJumpLocation) {
+  highlightLine() {
+    const { selectedLocation, selectedFrame } = this.props;
+    if (!selectedLocation) {
       return;
     }
 
     // Make sure to clean up after ourselves. Not only does this
     // cancel any existing animation, but it avoids it from
     // happening ever again (in case CodeMirror re-applies the
     // class, etc).
-    if (this.lastJumpLine) {
+    if (this.lastJumpLine !== null) {
       (0, _editor.clearLineClass)(this.state.editor.codeMirror, "highlight-line");
     }
 
-    const { sourceId, line: sourceLine } = this.pendingJumpLocation;
-    const line = (0, _editor.toEditorLine)(sourceId, sourceLine);
-    this.state.editor.alignLine(line);
+    let line = null;
+    if (selectedLocation.line >= 0) {
+      line = this.scrollToPosition();
+    }
 
     // We only want to do the flashing animation if it's not a debug
     // line, which has it's own styling.
     // Also, if it the first time the debugger is being loaded, we don't want
     // to flash the previously saved selected line.
-    if (this.lastJumpLine && (!this.props.selectedFrame || this.props.selectedFrame.location.line !== line)) {
+    if (line !== null && this.lastJumpLine !== null && (!selectedFrame || selectedFrame.location.line !== line)) {
       this.state.editor.codeMirror.addLineClass(line, "line", "highlight-line");
     }
 
     this.lastJumpLine = line;
     this.pendingJumpLocation = null;
   }
 
+  scrollToPosition() {
+    const { sourceId, line, column } = this.props.selectedLocation;
+    const editorLine = (0, _editor.toEditorLine)(sourceId, line);
+    (0, _editor.scrollToColumn)(this.state.editor.codeMirror, editorLine, column);
+    return editorLine;
+  }
+
   setSize(nextProps) {
     if (!this.state.editor) {
       return;
     }
 
     if (nextProps.startPanelSize !== this.props.startPanelSize || nextProps.endPanelSize !== this.props.endPanelSize) {
       this.state.editor.codeMirror.setSize();
     }
@@ -37160,17 +36353,16 @@ var _PaneToggle = __webpack_require__(14
 
 var _PaneToggle2 = _interopRequireDefault(_PaneToggle);
 
 __webpack_require__(1322);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class SourceFooter extends _react.PureComponent {
-
   prettyPrintButton() {
     const { selectedSource, togglePrettyPrint } = this.props;
     const sourceLoaded = selectedSource && (0, _source.isLoaded)(selectedSource.toJS());
 
     if (!(0, _editor.shouldShowPrettyPrint)(selectedSource)) {
       return;
     }
 
@@ -37365,17 +36557,16 @@ function getShortcuts() {
   return {
     shiftSearchAgainShortcut: searchAgainPrevKey,
     searchAgainShortcut: searchAgainKey,
     searchShortcut: searchKey
   };
 }
 
 class SearchBar extends _react.Component {
-
   constructor(props) {
     super(props);
 
     this.onEscape = e => {
       this.closeSearch(e);
     };
 
     this.clearSearch = () => {
@@ -37570,31 +36761,16 @@ class SearchBar extends _react.Component
 
     if (index == -1) {
       return L10N.getFormatStr("sourceSearch.resultsSummary1", count);
     }
 
     return L10N.getFormatStr("editor.searchResults", matchIndex + 1, count);
   }
 
-  renderSearchType() {
-    return _react2.default.createElement(
-      "div",
-      { className: "search-type-toggles" },
-      _react2.default.createElement(
-        "span",
-        {
-          className: "search-type-name",
-          onClick: () => this.props.setActiveSearch("symbol")
-        },
-        L10N.getStr("symbolSearch.search.functionsPlaceholder")
-      )
-    );
-  }
-
   render() {
     const { searchResults: { count }, searchOn } = this.props;
 
     if (!searchOn) {
       return _react2.default.createElement("div", null);
     }
 
     return _react2.default.createElement(
@@ -37609,17 +36785,16 @@ class SearchBar extends _react.Component
         onKeyUp: this.onKeyUp,
         handleNext: e => this.traverseResults(e, false),
         handlePrev: e => this.traverseResults(e, true),
         handleClose: this.closeSearch
       }),
       _react2.default.createElement(
         "div",
         { className: "search-bottom-bar" },
-        this.renderSearchType(),
         this.renderSearchModifiers()
       )
     );
   }
 }
 
 SearchBar.contextTypes = {
   shortcuts: _propTypes2.default.object
@@ -40645,17 +39820,16 @@ class Popover extends _react.Component {
     return this.renderPopover();
   }
 }
 
 Popover.defaultProps = {
   onMouseLeave: () => {},
   type: "popover"
 };
-
 exports.default = Popover;
 
 /***/ }),
 /* 1587 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -40725,17 +39899,16 @@ var _visibleBreakpoints2 = _interopRequi
 
 var _breakpoint = __webpack_require__(1364);
 
 var _source = __webpack_require__(1356);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class Breakpoints extends _react.Component {
-
   shouldComponentUpdate(nextProps) {
     if (nextProps.selectedSource && !(0, _source.isLoaded)(nextProps.selectedSource.toJS())) {
       return false;
     }
 
     return true;
   }
 
@@ -40915,17 +40088,16 @@ const markerEl = document.createElement(
 
 function makeMarker() {
   const marker = markerEl.cloneNode(true);
   marker.className = "editor hit-marker";
   return marker;
 }
 
 class HitMarker extends _react.Component {
-
   addMarker() {
     const hitData = this.props.hitData;
     const line = hitData.line - 1;
 
     this.props.editor.setGutterMarker(line, "hit-markers", makeMarker());
 
     this.props.editor.addLineClass(line, "line", "hit-marker");
   }
@@ -41290,49 +40462,56 @@ var _editor = __webpack_require__(1358);
 
 var _sourceDocuments = __webpack_require__(1436);
 
 var _reactRedux = __webpack_require__(1189);
 
 var _selectors = __webpack_require__(1352);
 
 class DebugLine extends _react.Component {
-
   constructor() {
     super();
     this.state = { debugExpression: { clear: () => {} } };
   }
 
   componentDidMount() {
-    this.setDebugLine(this.props.selectedFrame, this.props.selectedLocation, this.props.editor);
+    this.setDebugLine(this.props.pauseInfo, this.props.selectedFrame, this.props.selectedLocation, this.props.editor);
   }
 
   componentWillReceiveProps(nextProps) {
     this.clearDebugLine(this.props.selectedFrame, this.props.editor);
-    this.setDebugLine(nextProps.selectedFrame, nextProps.selectedLocation, nextProps.editor);
+    this.setDebugLine(nextProps.pauseInfo, nextProps.selectedFrame, nextProps.selectedLocation, nextProps.editor);
   }
 
   componentWillUnmount() {
     this.clearDebugLine(this.props.selectedFrame, this.props.editor);
   }
 
-  setDebugLine(selectedFrame, selectedLocation, editor) {
+  setDebugLine(pauseInfo, selectedFrame, selectedLocation, editor) {
     if (!selectedFrame) {
       return;
     }
+
     const { location, location: { sourceId } } = selectedFrame;
-    const { line, column } = (0, _editor.toEditorPosition)(sourceId, location);
-
     const doc = (0, _sourceDocuments.getDocument)(sourceId);
     if (!doc) {
       return;
     }
 
-    doc.addLineClass(line, "line", "new-debug-line");
-    const debugExpression = (0, _editor.markText)(editor, "debug-expression", {
+    const { line, column } = (0, _editor.toEditorPosition)(sourceId, location);
+
+    // make sure the line is visible
+    if (editor && editor.alignLine) {
+      editor.alignLine(line);
+    }
+
+    const { markTextClass, lineClass } = this.getTextClasses(pauseInfo);
+    doc.addLineClass(line, "line", lineClass);
+
+    const debugExpression = (0, _editor.markText)(editor, markTextClass, {
       start: { line, column },
       end: { line, column: null }
     });
     this.setState({ debugExpression });
   }
 
   clearDebugLine(selectedFrame, editor) {
     if (!selectedFrame) {
@@ -41346,27 +40525,39 @@ class DebugLine extends _react.Component
 
     const editorLine = line - 1;
     const doc = (0, _sourceDocuments.getDocument)(sourceId);
     if (!doc) {
       return;
     }
 
     doc.removeLineClass(editorLine, "line", "new-debug-line");
+    doc.removeLineClass(editorLine, "line", "new-debug-line-error");
+  }
+
+  getTextClasses(pauseInfo) {
+    if (pauseInfo && pauseInfo.why.type === "exception") {
+      return {
+        markTextClass: "debug-expression-error",
+        lineClass: "new-debug-line-error"
+      };
+    }
+    return { markTextClass: "debug-expression", lineClass: "new-debug-line" };
   }
 
   render() {
     return null;
   }
 }
 
 exports.DebugLine = DebugLine;
 exports.default = (0, _reactRedux.connect)(state => ({
   selectedLocation: (0, _selectors.getSelectedLocation)(state),
-  selectedFrame: (0, _selectors.getSelectedFrame)(state)
+  selectedFrame: (0, _selectors.getSelectedFrame)(state),
+  pauseInfo: (0, _selectors.getPause)(state)
 }))(DebugLine);
 
 /***/ }),
 /* 1594 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -41584,31 +40775,37 @@ class GutterContextMenuComponent extends
   showMenu(nextProps) {
     const { contextMenu } = nextProps,
           props = _objectWithoutProperties(nextProps, ["contextMenu"]);
     const { event } = contextMenu;
     const sourceId = props.selectedSource ? props.selectedSource.get("id") : "";
     const line = (0, _editor.lineAtHeight)(props.editor, sourceId, event);
     const breakpoint = nextProps.breakpoints.find(bp => bp.location.line === line);
 
+    if (props.emptyLines.includes(line)) {
+      return;
+    }
+
     gutterMenu(_extends({ event, sourceId, line, breakpoint }, props));
   }
 
   render() {
     return null;
   }
 }
 
 exports.default = (0, _reactRedux.connect)(state => {
+  const selectedSource = (0, _selectors.getSelectedSource)(state);
   return {
     selectedLocation: (0, _selectors.getSelectedLocation)(state),
-    selectedSource: (0, _selectors.getSelectedSource)(state),
+    selectedSource: selectedSource,
     breakpoints: (0, _selectors.getVisibleBreakpoints)(state),
     pauseData: (0, _selectors.getPause)(state),
-    contextMenu: (0, _selectors.getContextMenu)(state)
+    contextMenu: (0, _selectors.getContextMenu)(state),
+    emptyLines: selectedSource ? (0, _selectors.getEmptyLines)(state, selectedSource.toJS()) : []
   };
 }, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(GutterContextMenuComponent);
 
 /***/ }),
 /* 1596 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -41681,33 +40878,34 @@ function getMenuItems(event, {
     id: "node-menu-copy-source",
     label: copySourceLabel,
     accesskey: copySourceKey,
     disabled: selectionText.length === 0,
     click: () => (0, _clipboard.copyToTheClipboard)(selectionText)
   };
 
   const { line } = editor.codeMirror.coordsChar({
-    left: event.clientX
+    left: event.clientX,
+    top: event.clientY
   });
 
   const sourceLocation = (0, _editor.getSourceLocationFromMouseEvent)(editor, selectedLocation, event);
 
   const pairedType = (0, _devtoolsSourceMap.isOriginalId)(selectedLocation.sourceId) ? L10N.getStr("generated") : L10N.getStr("original");
 
   const jumpLabel = {
     accesskey: L10N.getStr("editor.jumpToMappedLocation1.accesskey"),
     disabled: false,
     label: L10N.getFormatStr("editor.jumpToMappedLocation1", pairedType),
     click: () => jumpToMappedLocation(sourceLocation)
   };
 
   const watchExpressionLabel = {
-    accesskey: L10N.getStr("expressions.placeholder.accesskey"),
-    label: L10N.getStr("expressions.placeholder"),
+    accesskey: L10N.getStr("expressions.accesskey"),
+    label: L10N.getStr("expressions.label"),
     click: () => addExpression(editor.codeMirror.getSelection())
   };
 
   const blackBoxMenuItem = {
     id: "node-menu-blackbox",
     label: toggleBlackBoxLabel,
     accesskey: blackboxKey,
     disabled: false,
@@ -41854,20 +41052,16 @@ var _selectors = __webpack_require__(135
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class ConditionalPanel extends _react.PureComponent {
 
   constructor() {
     super();
 
-    this.setInput = node => {
-      this.input = node;
-    };
-
     this.saveAndClose = () => {
       if (this.input) {
         this.setBreakpoint(this.input.value);
       }
 
       this.props.closeConditionalPanel();
     };
 
@@ -41875,17 +41069,22 @@ class ConditionalPanel extends _react.Pu
       if (e.key === "Enter") {
         this.saveAndClose();
       } else if (e.key === "Escape") {
         this.props.closeConditionalPanel();
       }
     };
 
     this.cbPanel = null;
-    this.input = {};
+  }
+
+  keepFocusOnInput() {
+    if (this.input) {
+      this.input.focus();
+    }
   }
 
   setBreakpoint(condition) {
     const { selectedLocation, line } = this.props;
     const sourceId = selectedLocation ? selectedLocation.sourceId : "";
     const location = { sourceId, line };
     return this.props.setBreakpointCondition(location, { condition });
   }
@@ -41908,36 +41107,42 @@ class ConditionalPanel extends _react.Pu
     const { selectedLocation, line, editor } = props;
     const sourceId = selectedLocation ? selectedLocation.sourceId : "";
 
     const editorLine = (0, _editor.toEditorLine)(sourceId, line);
     this.cbPanel = editor.codeMirror.addLineWidget(editorLine, this.renderConditionalPanel(props), {
       coverGutter: true,
       noHScroll: false
     });
-    this.input.focus();
+    if (this.input) {
+      this.input.focus();
+    }
   }
 
   renderConditionalPanel(props) {
     const { breakpoint } = props;
     const condition = breakpoint ? breakpoint.condition : "";
     const panel = document.createElement("div");
     _reactDom2.default.render(_react2.default.createElement(
       "div",
-      { className: "conditional-breakpoint-panel" },
+      {
+        className: "conditional-breakpoint-panel",
+        onClick: () => this.keepFocusOnInput(),
+        onBlur: this.props.closeConditionalPanel
+      },
       _react2.default.createElement(
         "div",
         { className: "prompt" },
         "\xBB"
       ),
       _react2.default.createElement("input", {
         defaultValue: condition,
         placeholder: L10N.getStr("editor.conditionalPanel.placeholder"),
         onKeyDown: this.onKey,
-        ref: this.setInput
+        ref: input => this.input = input
       }),
       _react2.default.createElement(_Close2.default, {
         handleClick: this.props.closeConditionalPanel,
         buttonClass: "big",
         tooltip: L10N.getStr("editor.conditionalPanel.close")
       })
     ), panel);
     return panel;
@@ -42335,17 +41540,16 @@ function renderSourceLocation(source, li
   return _react2.default.createElement(
     "div",
     { className: "location" },
     `${(0, _utils.endTruncateStr)(filename, 30)}: ${bpLocation}`
   );
 }
 
 class Breakpoints extends _react.PureComponent {
-
   shouldComponentUpdate(nextProps, nextState) {
     const { breakpoints } = this.props;
     return breakpoints !== nextProps.breakpoints;
   }
 
   handleCheckbox(breakpoint) {
     if (breakpoint.loading) {
       return;
@@ -42895,18 +42099,18 @@ var _selectors = __webpack_require__(135
 __webpack_require__(1338);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 const NUM_FRAMES_SHOWN = 7;
 
 class Frames extends _react.Component {
 
-  constructor(...args) {
-    super(...args);
+  constructor(props) {
+    super(props);
 
     this.state = {
       showAllFrames: false
     };
 
     this.toggleFramesDisplay = this.toggleFramesDisplay.bind(this);
     this.copyStackTrace = this.copyStackTrace.bind(this);
     this.toggleFrameworkGrouping = this.toggleFrameworkGrouping.bind(this);
@@ -42967,17 +42171,17 @@ class Frames extends _react.Component {
       framesOrGroups.map(frameOrGroup => frameOrGroup.id ? _react2.default.createElement(_Frame2.default, {
         frame: frameOrGroup,
         toggleFrameworkGrouping: this.toggleFrameworkGrouping,
         copyStackTrace: this.copyStackTrace,
         frameworkGroupingOn: frameworkGroupingOn,
         selectFrame: selectFrame,
         selectedFrame: selectedFrame,
         toggleBlackBox: toggleBlackBox,
-        key: frameOrGroup.id
+        key: String(frameOrGroup.id)
       }) : _react2.default.createElement(_Group2.default, {
         group: frameOrGroup,
         toggleFrameworkGrouping: this.toggleFrameworkGrouping,
         copyStackTrace: this.copyStackTrace,
         frameworkGroupingOn: frameworkGroupingOn,
         selectFrame: selectFrame,
         selectedFrame: selectedFrame,
         toggleBlackBox: toggleBlackBox,
@@ -43488,17 +42692,16 @@ var _Svg = __webpack_require__(1359);
 
 var _Svg2 = _interopRequireDefault(_Svg);
 
 __webpack_require__(1341);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class Accordion extends _react.Component {
-
   constructor(props) {
     super();
 
     this.renderContainer = (item, i) => {
       const { opened, created } = this.state;
       const containerClassName = `${item.header.toLowerCase().replace(/\s/g, "-")}-pane`;
 
       return _react2.default.createElement(
@@ -43597,20 +42800,16 @@ var _reactRedux = __webpack_require__(11
 var _redux = __webpack_require__(3);
 
 var _classnames = __webpack_require__(175);
 
 var _classnames2 = _interopRequireDefault(_classnames);
 
 var _selectors = __webpack_require__(1352);
 
-var _Svg = __webpack_require__(1359);
-
-var _Svg2 = _interopRequireDefault(_Svg);
-
 var _text = __webpack_require__(1387);
 
 var _actions = __webpack_require__(1354);
 
 var _actions2 = _interopRequireDefault(_actions);
 
 __webpack_require__(1295);
 
@@ -43675,22 +42874,21 @@ function debugBtn(onClick, type, classNa
     "aria-label": tooltip,
     title: tooltip,
     disabled
   };
 
   return _react2.default.createElement(
     "button",
     _extends({ className: (0, _classnames2.default)(type, className) }, props),
-    _react2.default.createElement(_Svg2.default, { name: type })
+    _react2.default.createElement("img", { className: type })
   );
 }
 
 class CommandBar extends _react.Component {
-
   componentWillUnmount() {
     const shortcuts = this.context.shortcuts;
     COMMANDS.forEach(action => shortcuts.off(getKey(action)));
     if (isMacOS) {
       COMMANDS.forEach(action => shortcuts.off(getKeyForOS("WINNT", action)));
     }
   }
 
@@ -43824,17 +43022,16 @@ function debugBtn(onClick, type, classNa
   return _react2.default.createElement(
     "button",
     _extends({ className: (0, _classnames2.default)(type, className) }, props),
     "?"
   );
 }
 
 class UtilsBar extends _react.Component {
-
   renderUtilButtons() {
     return [debugBtn(this.props.toggleShortcutsModal, "shortcut", "active", L10N.getStr("shortcuts.buttonName"), false)];
   }
 
   render() {
     return _react2.default.createElement(
       "div",
       {
@@ -44115,33 +43312,33 @@ var _scopes = __webpack_require__(1612);
 
 var _devtoolsReps = __webpack_require__(1408);
 
 __webpack_require__(1296);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class Scopes extends _react.PureComponent {
-
   constructor(props, ...args) {
     const { pauseInfo, selectedFrame, frameScopes } = props;
 
     super(props, ...args);
 
     this.state = {
       scopes: (0, _scopes.getScopes)(pauseInfo, selectedFrame, frameScopes)
     };
   }
 
   componentWillReceiveProps(nextProps) {
-    const { pauseInfo, selectedFrame } = this.props;
+    const { pauseInfo, selectedFrame, frameScopes } = this.props;
     const pauseInfoChanged = pauseInfo !== nextProps.pauseInfo;
-    const selectedFrameChange = selectedFrame !== nextProps.selectedFrame;
-
-    if (pauseInfoChanged || selectedFrameChange) {
+    const selectedFrameChanged = selectedFrame !== nextProps.selectedFrame;
+    const frameScopesChanged = frameScopes !== nextProps.frameScopes;
+
+    if (pauseInfoChanged || selectedFrameChanged || frameScopesChanged) {
       this.setState({
         scopes: (0, _scopes.getScopes)(nextProps.pauseInfo, nextProps.selectedFrame, nextProps.frameScopes)
       });
     }
   }
 
   render() {
     const { pauseInfo, loadObjectProperties, loadedObjects } = this.props;
@@ -44402,17 +43599,16 @@ var _PaneToggle = __webpack_require__(14
 
 var _PaneToggle2 = _interopRequireDefault(_PaneToggle);
 
 __webpack_require__(1343);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class WelcomeBox extends _react.Component {
-
   renderToggleButton() {
     const { horizontal, endPanelCollapsed, togglePaneCollapse } = this.props;
     if (horizontal) {
       return;
     }
 
     return _react2.default.createElement(_PaneToggle2.default, {
       position: "end",
@@ -44424,30 +43620,30 @@ class WelcomeBox extends _react.Componen
 
   render() {
     const searchSourcesShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2"));
 
     const searchProjectShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("projectTextSearch.key"));
 
     const searchSourcesLabel = L10N.getStr("welcome.search").substring(2);
     const searchProjectLabel = L10N.getStr("welcome.findInFiles").substring(2);
-    const { setActiveSearch } = this.props;
+    const { setActiveSearch, openQuickOpen } = this.props;
 
     return _react2.default.createElement(
       "div",
       { className: "welcomebox" },
       _react2.default.createElement(
         "div",
         { className: "alignlabel small-size-layout" },
         _react2.default.createElement(
           "div",
           { className: "shortcutFunction" },
           _react2.default.createElement(
             "p",
-            { onClick: setActiveSearch.bind(null, "source") },
+            { onClick: () => openQuickOpen() },
             _react2.default.createElement(
               "span",
               { className: "shortcutKey" },
               searchSourcesShortcut
             ),
             searchSourcesLabel
           ),
           _react2.default.createElement(
@@ -44466,31 +43662,31 @@ class WelcomeBox extends _react.Componen
       _react2.default.createElement(
         "div",
         { className: "alignlabel normal-layout" },
<