Merge inbound to mozilla-central. a=merge
authorOana Pop Rus <opoprus@mozilla.com>
Wed, 13 Mar 2019 12:09:03 +0200
changeset 521686 aecc70710359
parent 521685 588208caeaf8 (current diff)
parent 521684 00b6a6203f0f (diff)
child 521687 121d045e218a
push id10867
push userdvarga@mozilla.com
push dateThu, 14 Mar 2019 15:20:45 +0000
treeherdermozilla-beta@abad13547875 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone67.0a1
first release with
nightly linux32
aecc70710359 / 67.0a1 / 20190313100914 / files
nightly linux64
aecc70710359 / 67.0a1 / 20190313100914 / files
nightly mac
aecc70710359 / 67.0a1 / 20190313100914 / files
nightly win32
aecc70710359 / 67.0a1 / 20190313100914 / files
nightly win64
aecc70710359 / 67.0a1 / 20190313100914 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
browser/locales/en-US/chrome/browser/browser.dtd
devtools/client/debugger/new/src/reducers/pause.js
devtools/client/debugger/new/src/reducers/sources.js
devtools/client/debugger/new/src/utils/test-head.js
devtools/client/debugger/new/test/mochitest/helpers.js
--- a/browser/components/extensions/parent/ext-chrome-settings-overrides.js
+++ b/browser/components/extensions/parent/ext-chrome-settings-overrides.js
@@ -225,17 +225,17 @@ this.chrome_settings_overrides = class e
                 // This is a hack because we don't have the browser of
                 // the actual install. This means the popup might show
                 // in a different window. Will be addressed in a followup bug.
                 browser: windowTracker.topWindow.gBrowser.selectedBrowser,
                 name: this.extension.name,
                 icon: this.extension.iconURL,
                 currentEngine: defaultEngine.name,
                 newEngine: engineName,
-                resolve(allow) {
+                respond(allow) {
                   if (allow) {
                     ExtensionSettingsStore.addSetting(
                       extension.id, DEFAULT_SEARCH_STORE_TYPE, DEFAULT_SEARCH_SETTING_NAME, engineName, () => defaultEngine.name);
                     Services.search.defaultEngine = Services.search.getEngineByName(engineName);
                   }
                 },
               },
             };
--- a/browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js
+++ b/browser/components/extensions/test/browser/browser_ext_settings_overrides_default_search.js
@@ -40,16 +40,91 @@ add_task(async function test_extension_s
 
   is((await Services.search.getDefault()).name, "DuckDuckGo", "Default engine is DuckDuckGo");
 
   await ext1.unload();
 
   is((await Services.search.getDefault()).name, defaultEngineName, `Default engine is ${defaultEngineName}`);
 });
 
+// Test the popup displayed when trying to add a non-built-in default
+// search engine.
+add_task(async function test_extension_setting_default_engine_external() {
+  const NAME = "Example Engine";
+
+  // Load an extension that tries to set the default engine,
+  // and wait for the ensuing prompt.
+  async function startExtension(win = window) {
+    let extension = ExtensionTestUtils.loadExtension({
+      manifest: {
+        "chrome_settings_overrides": {
+          "search_provider": {
+            "name": NAME,
+            "search_url": "https://example.com/?q={searchTerms}",
+            "is_default": true,
+          },
+        },
+      },
+      useAddonManager: "temporary",
+    });
+
+    let [panel] = await Promise.all([
+      promisePopupNotificationShown("addon-webext-defaultsearch", win),
+      extension.startup(),
+    ]);
+
+    isnot(panel, null, "Doorhanger was displayed for non-built-in default engine");
+
+    return {panel, extension};
+  }
+
+  // First time around, don't accept the default engine.
+  let {panel, extension} = await startExtension();
+  panel.secondaryButton.click();
+
+  // There is no explicit event we can wait for to know when the click
+  // callback has been fully processed.  One spin through the Promise
+  // microtask queue should be enough.  If this wait isn't long enough,
+  // the test below where we accept the prompt will fail.
+  await Promise.resolve();
+
+  is((await Services.search.getDefault()).name, defaultEngineName,
+     "Default engine was not changed after rejecting prompt");
+
+  await extension.unload();
+
+  // Do it again, this time accept the prompt.
+  ({panel, extension} = await startExtension());
+
+  panel.button.click();
+  await Promise.resolve();
+
+  is((await Services.search.getDefault()).name, NAME,
+     "Default engine was changed after accepting prompt");
+
+  await extension.unload();
+
+  is((await Services.search.getDefault()).name, defaultEngineName,
+     "Default engine is reverted after uninstalling extension.");
+
+  // One more time, this time close the window where the prompt
+  // appears instead of explicitly accepting or denying it.
+  let win = await BrowserTestUtils.openNewBrowserWindow();
+  await BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank");
+
+  ({extension} = await startExtension(win));
+
+  await BrowserTestUtils.closeWindow(win);
+
+  is((await Services.search.getDefault()).name, defaultEngineName,
+     "Default engine is unchanged when prompt is dismissed");
+
+  await extension.unload();
+});
+
 /* This tests that uninstalling add-ons maintains the proper
  * search default. */
 add_task(async function test_extension_setting_multiple_default_engine() {
   let ext1 = ExtensionTestUtils.loadExtension({
     manifest: {
       "chrome_settings_overrides": {
         "search_provider": {
           "name": "DuckDuckGo",
--- a/browser/components/extensions/test/browser/browser_ext_user_events.js
+++ b/browser/components/extensions/test/browser/browser_ext_user_events.js
@@ -1,36 +1,10 @@
 "use strict";
 
-/**
- * Wait for the given PopupNotification to display
- *
- * @param {string} name
- *        The name of the notification to wait for.
- *
- * @returns {Promise}
- *          Resolves with the notification window.
- */
-function promisePopupNotificationShown(name) {
-  return new Promise(resolve => {
-    function popupshown() {
-      let notification = PopupNotifications.getNotification(name);
-      if (!notification) { return; }
-
-      ok(notification, `${name} notification shown`);
-      ok(PopupNotifications.isPanelOpen, "notification panel open");
-
-      PopupNotifications.panel.removeEventListener("popupshown", popupshown);
-      resolve(PopupNotifications.panel.firstElementChild);
-    }
-
-    PopupNotifications.panel.addEventListener("popupshown", popupshown);
-  });
-}
-
 // Test that different types of events are all considered
 // "handling user input".
 add_task(async function testSources() {
   let extension = ExtensionTestUtils.loadExtension({
     async background() {
       async function request(perm) {
         try {
           let result = await browser.permissions.request({
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -3,17 +3,17 @@
 "use strict";
 
 /* exported CustomizableUI makeWidgetId focusWindow forceGC
  *          getBrowserActionWidget
  *          clickBrowserAction clickPageAction
  *          getBrowserActionPopup getPageActionPopup getPageActionButton
  *          openBrowserActionPanel
  *          closeBrowserAction closePageAction
- *          promisePopupShown promisePopupHidden
+ *          promisePopupShown promisePopupHidden promisePopupNotificationShown
  *          toggleBookmarksToolbar
  *          openContextMenu closeContextMenu
  *          openContextMenuInSidebar openContextMenuInPopup
  *          openExtensionContextMenu closeExtensionContextMenu
  *          openActionContextMenu openSubmenu closeActionContextMenu
  *          openTabContextMenu closeTabContextMenu
  *          openToolsMenu closeToolsMenu
  *          imageBuffer imageBufferFromDataURI
@@ -154,16 +154,44 @@ function promisePopupHidden(popup) {
     let onPopupHidden = event => {
       popup.removeEventListener("popuphidden", onPopupHidden);
       resolve();
     };
     popup.addEventListener("popuphidden", onPopupHidden);
   });
 }
 
+/**
+ * Wait for the given PopupNotification to display
+ *
+ * @param {string} name
+ *        The name of the notification to wait for.
+ * @param {Window} [win]
+ *        The chrome window in which to wait for the notification.
+ *
+ * @returns {Promise}
+ *          Resolves with the notification window.
+ */
+function promisePopupNotificationShown(name, win = window) {
+  return new Promise(resolve => {
+    function popupshown() {
+      let notification = win.PopupNotifications.getNotification(name);
+      if (!notification) { return; }
+
+      ok(notification, `${name} notification shown`);
+      ok(win.PopupNotifications.isPanelOpen, "notification panel open");
+
+      win.PopupNotifications.panel.removeEventListener("popupshown", popupshown);
+      resolve(win.PopupNotifications.panel.firstElementChild);
+    }
+
+    win.PopupNotifications.panel.addEventListener("popupshown", popupshown);
+  });
+}
+
 function promisePossiblyInaccurateContentDimensions(browser) {
   return ContentTask.spawn(browser, null, async function() {
     function copyProps(obj, props) {
       let res = {};
       for (let prop of props) {
         res[prop] = obj[prop];
       }
       return res;
--- a/browser/locales/en-US/chrome/browser/accounts.properties
+++ b/browser/locales/en-US/chrome/browser/accounts.properties
@@ -97,8 +97,12 @@ unnamedTabsArrivingNotificationMultiple2
 # This version is used when we don't know any device names.
 unnamedTabsArrivingNotificationNoDevice.body = #1 tab has arrived;#1 tabs have arrived
 
 # LOCALIZATION NOTE (singleTabArrivingWithTruncatedURL.body):
 # Used when a tab from a remote device arrives but the URL must be truncated.
 # Should display the URL with an indication that it's benen truncated.
 # %S is the portion of the URL that remains after truncation.
 singleTabArrivingWithTruncatedURL.body = %S…
+
+# LOCALIZATION NOTE (account.title):
+# Used as a default header for the FxA toolbar menu.
+account.title = Account
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -209,16 +209,37 @@ These should match what Safari and other
 <!ENTITY fullScreenMinimize.tooltip "Minimize">
 <!ENTITY fullScreenRestore.tooltip "Restore">
 <!ENTITY fullScreenClose.tooltip "Close">
 <!ENTITY fullScreenAutohide.label "Hide Toolbars">
 <!ENTITY fullScreenAutohide.accesskey "H">
 <!ENTITY fullScreenExit.label "Exit Full Screen Mode">
 <!ENTITY fullScreenExit.accesskey "F">
 
+ <!-- LOCALIZATION NOTE (fxa.signin) Used to define the different labels
+     for the Firefox Account toolbar signin menu screen. -->
+<!ENTITY fxa.signin.callout.label "Take Firefox with You">
+<!ENTITY fxa.signin.description.label "Get your bookmarks, history, passwords and other settings on all your devices.">
+<!ENTITY fxa.signin.button.label "Turn on &syncBrand.shortName.label;…">
+
+<!-- LOCALIZATION NOTE (fxa.unverified) Used to define the different labels
+     for the Firefox Account toolbar unverified menu screen. -->
+<!ENTITY fxa.unverified.callout.label "Check Your Email">
+<!ENTITY fxa.unverified.description.label "You’ll need to verify your account before you can sync.">
+<!ENTITY fxa.unverified.button.label "Open &syncBrand.shortName.label; Settings…">
+
+<!-- LOCALIZATION NOTE (fxa.menu) Used to define the different labels
+     for the Firefox Account toolbart menu screen. The `Signed in as` text is
+     followed by the user's email. -->
+<!ENTITY fxa.menu.signedInAs.label "Signed in as">
+<!ENTITY fxa.menu.manageAccount.label "Manage Account…">
+<!ENTITY fxa.menu.syncSettings.label "&syncBrand.shortName.label; Settings…">
+<!ENTITY fxa.menu.connectAnotherDevice.label "&syncedTabs.sidebar.connectAnotherDevice;">
+<!ENTITY fxa.menu.firefoxAccount "&syncBrand.fxAccount.label;">
+
 <!-- LOCALIZATION NOTE (fullscreenWarning.beforeDomain.label,
      fullscreenWarning.afterDomain.label): these two strings are used
      respectively before and after the domain requiring fullscreen.
      Localizers can use one of them, or both, to better adapt this
      sentence to their language. -->
 <!ENTITY fullscreenWarning.beforeDomain.label "">
 <!ENTITY fullscreenWarning.afterDomain.label "is now full screen">
 <!ENTITY fullscreenWarning.generic.label "This document is now full screen">
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -266,29 +266,30 @@ var ExtensionsUI = {
 
       // If we don't have any promptable permissions, just proceed
       if (strings.msgs.length == 0) {
         resolve(true);
         return;
       }
       resolve(this.showPermissionsPrompt(browser, strings, icon));
     } else if (topic == "webextension-defaultsearch-prompt") {
-      let {browser, name, icon, resolve, currentEngine, newEngine} = subject.wrappedJSObject;
+      let {browser, name, icon, respond, currentEngine, newEngine} = subject.wrappedJSObject;
 
       let bundle = Services.strings.createBundle(BROWSER_PROPERTIES);
 
       let strings = {};
       strings.acceptText = bundle.GetStringFromName("webext.defaultSearchYes.label");
       strings.acceptKey = bundle.GetStringFromName("webext.defaultSearchYes.accessKey");
       strings.cancelText = bundle.GetStringFromName("webext.defaultSearchNo.label");
       strings.cancelKey = bundle.GetStringFromName("webext.defaultSearchNo.accessKey");
       strings.addonName = name;
       strings.text = bundle.formatStringFromName("webext.defaultSearch.description",
                                                  ["<>", currentEngine, newEngine], 3);
-      resolve(this.showDefaultSearchPrompt(browser, strings, icon));
+
+      this.showDefaultSearchPrompt(browser, strings, icon).then(respond);
     }
   },
 
   // Create a set of formatted strings for a permission prompt
   _buildStrings(info) {
     let bundle = Services.strings.createBundle(BROWSER_PROPERTIES);
     let brandBundle = Services.strings.createBundle(BRAND_PROPERTIES);
     let appName = brandBundle.GetStringFromName("brandShortName");
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -896,33 +896,32 @@ NS_INTERFACE_MAP_END
  **/
 
 // Initialize our static variables.
 uintptr_t CanvasRenderingContext2D::sNumLivingContexts = 0;
 DrawTarget* CanvasRenderingContext2D::sErrorTarget = nullptr;
 
 CanvasRenderingContext2D::CanvasRenderingContext2D(
     layers::LayersBackend aCompositorBackend)
-    : // these are the default values from the Canvas spec
+    :  // these are the default values from the Canvas spec
       mWidth(0),
       mHeight(0),
       mZero(false),
       mOpaqueAttrValue(false),
       mContextAttributesHasAlpha(true),
       mOpaque(false),
       mResetLayer(true),
       mIPC(false),
       mHasPendingStableStateCallback(false),
       mIsEntireFrameInvalid(false),
       mPredictManyRedrawCalls(false),
       mIsCapturedFrameInvalid(false),
       mPathTransformWillUpdate(false),
       mInvalidateCount(0),
       mWriteOnly(false) {
-
   sNumLivingContexts++;
 
   mShutdownObserver = new CanvasShutdownObserver(this);
   nsContentUtils::RegisterShutdownObserver(mShutdownObserver);
 }
 
 CanvasRenderingContext2D::~CanvasRenderingContext2D() {
   RemovePostRefreshObserver();
@@ -1100,18 +1099,17 @@ void CanvasRenderingContext2D::Redraw(co
     return;
   }
 
   SVGObserverUtils::InvalidateDirectRenderingObservers(mCanvasElement);
 
   mCanvasElement->InvalidateCanvasContent(&aR);
 }
 
-void CanvasRenderingContext2D::DidRefresh() {
-}
+void CanvasRenderingContext2D::DidRefresh() {}
 
 void CanvasRenderingContext2D::RedrawUser(const gfxRect& aR) {
   mIsCapturedFrameInvalid = true;
 
   if (mIsEntireFrameInvalid) {
     ++mInvalidateCount;
     return;
   }
@@ -1129,18 +1127,17 @@ bool CanvasRenderingContext2D::CopyBuffe
     return false;
   }
 
   aTarget.CopySurface(snapshot, aCopyRect, IntPoint());
   aOld.ReturnSnapshot(snapshot.forget());
   return true;
 }
 
-void CanvasRenderingContext2D::Demote() {
-}
+void CanvasRenderingContext2D::Demote() {}
 
 void CanvasRenderingContext2D::ScheduleStableStateCallback() {
   if (mHasPendingStableStateCallback) {
     return;
   }
   mHasPendingStableStateCallback = true;
 
   nsContentUtils::RunInStableState(
@@ -1178,18 +1175,18 @@ void CanvasRenderingContext2D::RestoreCl
         mTarget->PushClip(clipOrTransform.clip);
       } else {
         mTarget->SetTransform(clipOrTransform.transform);
       }
     }
   }
 }
 
-bool CanvasRenderingContext2D::EnsureTarget(
-    const gfx::Rect* aCoveredRect, bool aWillClear) {
+bool CanvasRenderingContext2D::EnsureTarget(const gfx::Rect* aCoveredRect,
+                                            bool aWillClear) {
   if (AlreadyShutDown()) {
     gfxCriticalError() << "Attempt to render into a Canvas2d after shutdown.";
     SetErrorState();
     return false;
   }
 
   if (mTarget) {
     return true;
@@ -1253,17 +1250,18 @@ bool CanvasRenderingContext2D::EnsureTar
     SetErrorState();
     return false;
   }
 
   MOZ_ASSERT(newTarget);
   MOZ_ASSERT(newProvider);
 
   bool needsClear = !canDiscardContent;
-  if (newTarget->GetBackendType() == gfx::BackendType::SKIA && (needsClear || !aWillClear)) {
+  if (newTarget->GetBackendType() == gfx::BackendType::SKIA &&
+      (needsClear || !aWillClear)) {
     // Skia expects the unused X channel to contains 0xFF even for opaque
     // operations so we can't skip clearing in that case, even if we are going
     // to cover the entire canvas in the next drawing operation.
     newTarget->ClearRect(canvasRect);
     needsClear = false;
   }
 
   // Try to copy data from the previous buffer provider if there is one.
@@ -1367,18 +1365,20 @@ bool CanvasRenderingContext2D::TryShared
        mBufferProvider->GetType() == LayersBackend::LAYERS_WR)) {
     // we are already using a shared buffer provider, we are allocating a new
     // one because the current one failed so let's just fall back to the basic
     // provider.
     return false;
   }
 
 #ifdef XP_WIN
-  // Bug 1285271 - Disable shared buffer provider on Windows with D2D due to instability
-  if (gfxPlatform::GetPlatform()->GetPreferredCanvasBackend() == BackendType::DIRECT2D1_1) {
+  // Bug 1285271 - Disable shared buffer provider on Windows with D2D due to
+  // instability
+  if (gfxPlatform::GetPlatform()->GetPreferredCanvasBackend() ==
+      BackendType::DIRECT2D1_1) {
     return false;
   }
 #endif
 
   RefPtr<LayerManager> layerManager =
       LayerManagerFromCanvasElement(mCanvasElement);
 
   if (!layerManager) {
@@ -1404,16 +1404,24 @@ bool CanvasRenderingContext2D::TryBasicT
     RefPtr<gfx::DrawTarget>& aOutDT,
     RefPtr<layers::PersistentBufferProvider>& aOutProvider) {
   aOutDT = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(
       GetSize(), GetSurfaceFormat());
   if (!aOutDT) {
     return false;
   }
 
+  // See Bug 1524554 - this forces DT initialization.
+  aOutDT->ClearRect(gfx::Rect());
+
+  if (!aOutDT->IsValid()) {
+    aOutDT = nullptr;
+    return false;
+  }
+
   aOutProvider = new PersistentBufferProviderBasic(aOutDT);
   return true;
 }
 
 NS_IMETHODIMP
 CanvasRenderingContext2D::SetDimensions(int32_t aWidth, int32_t aHeight) {
   // Zero sized surfaces can cause problems.
   mZero = false;
@@ -4313,18 +4321,18 @@ void CanvasRenderingContext2D::DrawImage
 
     if (mCanvasElement) {
       CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, res.mPrincipal,
                                             res.mIsWriteOnly, res.mCORSUsed);
     }
 
     if (res.mSourceSurface) {
       if (res.mImageRequest) {
-        CanvasImageCache::NotifyDrawImage(
-            element, mCanvasElement, res.mSourceSurface, imgSize);
+        CanvasImageCache::NotifyDrawImage(element, mCanvasElement,
+                                          res.mSourceSurface, imgSize);
       }
       srcSurf = res.mSourceSurface;
     } else {
       drawInfo = res.mDrawInfo;
     }
   }
 
   if (aOptional_argc == 0) {
--- a/gfx/layers/SourceSurfaceSharedData.cpp
+++ b/gfx/layers/SourceSurfaceSharedData.cpp
@@ -17,16 +17,18 @@
  * If defined, this makes SourceSurfaceSharedData::Finalize memory protect the
  * underlying shared buffer in the producing process (the content or UI
  * process). Given flushing the page table is expensive, and its utility is
  * predominantly diagnostic (in case of overrun), turn it off by default.
  */
 #  define SHARED_SURFACE_PROTECT_FINALIZED
 #endif
 
+using namespace mozilla::layers;
+
 namespace mozilla {
 namespace gfx {
 
 bool SourceSurfaceSharedDataWrapper::Init(
     const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat,
     const SharedMemoryBasic::Handle& aHandle, base::ProcessId aCreatorPid) {
   MOZ_ASSERT(!mBuf);
   mSize = aSize;
--- a/gfx/layers/apz/public/IAPZCTreeManager.h
+++ b/gfx/layers/apz/public/IAPZCTreeManager.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_layers_IAPZCTreeManager_h
 #define mozilla_layers_IAPZCTreeManager_h
 
 #include <stdint.h>  // for uint64_t, uint32_t
 
 #include "mozilla/layers/LayersTypes.h"          // for TouchBehaviorFlags
 #include "mozilla/layers/ScrollableLayerGuid.h"  // for ScrollableLayerGuid, etc
+#include "mozilla/layers/ZoomConstraints.h"      // for ZoomConstraints
 #include "nsTArrayForwardDeclare.h"  // for nsTArray, nsTArray_Impl, etc
 #include "nsISupportsImpl.h"         // for MOZ_COUNT_CTOR, etc
 #include "Units.h"                   // for CSSRect, etc
 
 namespace mozilla {
 namespace layers {
 
 class APZInputBridge;
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -14,23 +14,24 @@
 #include "mozilla/Assertions.h"  // for MOZ_ASSERT_HELPER2
 #include "mozilla/gfx/CompositorHitTestInfo.h"
 #include "mozilla/gfx/Logging.h"              // for gfx::TreeLog
 #include "mozilla/gfx/Matrix.h"               // for Matrix4x4
 #include "mozilla/layers/APZInputBridge.h"    // for APZInputBridge
 #include "mozilla/layers/APZTestData.h"       // for APZTestData
 #include "mozilla/layers/IAPZCTreeManager.h"  // for IAPZCTreeManager
 #include "mozilla/layers/LayersTypes.h"
-#include "mozilla/layers/KeyboardMap.h"   // for KeyboardMap
-#include "mozilla/layers/TouchCounter.h"  // for TouchCounter
-#include "mozilla/RecursiveMutex.h"       // for RecursiveMutex
-#include "mozilla/RefPtr.h"               // for RefPtr
-#include "mozilla/TimeStamp.h"            // for mozilla::TimeStamp
-#include "mozilla/UniquePtr.h"            // for UniquePtr
-#include "nsCOMPtr.h"                     // for already_AddRefed
+#include "mozilla/layers/KeyboardMap.h"      // for KeyboardMap
+#include "mozilla/layers/TouchCounter.h"     // for TouchCounter
+#include "mozilla/layers/ZoomConstraints.h"  // for ZoomConstraints
+#include "mozilla/RecursiveMutex.h"          // for RecursiveMutex
+#include "mozilla/RefPtr.h"                  // for RefPtr
+#include "mozilla/TimeStamp.h"               // for mozilla::TimeStamp
+#include "mozilla/UniquePtr.h"               // for UniquePtr
+#include "nsCOMPtr.h"                        // for already_AddRefed
 
 #if defined(MOZ_WIDGET_ANDROID)
 #  include "mozilla/layers/AndroidDynamicToolbarAnimator.h"
 #endif  // defined(MOZ_WIDGET_ANDROID)
 
 namespace mozilla {
 class MultiTouchInput;
 
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_AsyncPanZoomController_h
 #define mozilla_layers_AsyncPanZoomController_h
 
 #include "CrossProcessMutex.h"
 #include "mozilla/layers/GeckoContentController.h"
 #include "mozilla/layers/RepaintRequest.h"
+#include "mozilla/layers/ZoomConstraints.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/RecursiveMutex.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Atomics.h"
 #include "InputData.h"
--- a/remote/doc/Usage.md
+++ b/remote/doc/Usage.md
@@ -9,27 +9,28 @@ three different programs/components runn
     and retrieve information out of Firefox;
 
   * the __agent__ that the client connects to which is an HTTPD living
     inside Firefox, facilitating communication between clients
     and targets;
 
   * and the __target__, which is the web document being debugging.
 
-As the remote agent is not compiled into Firefox by default, you
-will first have to get a build that has it.  You can read more
-about self-servicing such a build in the developer documentation,
-under [_Building_].
+The remote agent is not currently part of the default Firefox build.
+To self-service a build with it built in, you should follow the
+[_Building_] steps in the developer documentation.
 
-To check if your Firefox build has support for the new CDP-based
-remote debugger, you can check if its help message includes this:
+To check if your Firefox binary comes with the remote agent built
+in, you can look in its help message for this:
+
 
 	% ./firefox -h

-	  --remote-debugger [<host>][:<port>] Start the Firefox remote agent, which is 
+	  --remote-debugging-port <port>
+	  --remote-debugger [<host>][:<port>] Start the Firefox remote agent, which is
 	                     a low-level debugging interface based on the CDP protocol.
 	                     Defaults to listen on localhost:9222.

 
 As you will tell from the flag description, `--remote-debugger`
 takes an optional address spec as input:
 
 	[<host>][:<port>]
@@ -47,25 +48,21 @@ Other examples of address specs include:
 	:0
 
 The use of `localhost` in the first example above will, depending
 on whether the system supports IPv6, bind to both IP layers and
 accept incoming connections from either IPv4 or IPv6.  The second
 (`127.0.0.1`) and third (`[::1]`) examples will, respecitvely,
 force the HTTP to listen on IPv4 or IPv6.
 
-The fourth example will use the default hostname, which is `localhost`
-to listen on all available IP layers, but override the default port
-with the special-purpose port 0.  When you ask the remote agent to
-listen on port 0, the system will atomatically allocate an arbitrary
+The fourth example will use the default hostname, `localhost`, to
+listen on all available IP layers, but override the default port
+with the special purpose port 0.  When you ask the remote agent to
+listen on port 0, the system will atomically allocate an arbitrary
 free port.
 
-Allocating an atomic port can be useful if you want to be cautious
-race conditions.  The atomically allocated port will be somewhere
-in the ephemeral port range, which varies depending on your system
-and system configuration.
-
-As the atomic port is bound arbitrarily, there is intrisincly no
-way to detect upfront what it is.  However, Firefox will write the
-port it bound to, both to stdout and to the `remote.httpd.port`
-preference in the current profile’s _user.js_ file.
+Allocating an atomic port can be useful if you want to avoid race
+conditions.  The atomically allocated port will be somewhere in the
+ephemeral port range, which varies depending on your system and
+system configuration, but is always guaranteed to be free thus
+eliminating the risk of binding to a port that is already in use.
 
 [_Building_]: ./Building.html