diff --git a/docshell/test/chrome/Makefile.in b/docshell/test/chrome/Makefile.in
index 56af5314ea7c..d6d7ea57f872 100644
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -97,6 +97,7 @@ MOCHITEST_CHROME_FILES = \
test_private_hidden_window.html \
docshell_helpers.js \
generic.html \
+ test_bug846906.xul \
$(NULL)
ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)
diff --git a/docshell/test/chrome/test_bug846906.xul b/docshell/test/chrome/test_bug846906.xul
new file mode 100644
index 000000000000..1129d225115a
--- /dev/null
+++ b/docshell/test/chrome/test_bug846906.xul
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+ Test for Bug 846906
+
+
+
+
+
+
+
+ Mozilla Bug 846906
+
+
diff --git a/mach b/mach
deleted file mode 100755
index 9aba2825387e..000000000000
--- a/mach
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env python
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-from __future__ import print_function, unicode_literals
-
-import os
-import sys
-
-def ancestors(path):
- while path:
- yield path
- (path, child) = os.path.split(path)
- if child == "":
- break
-
-def load_mach(topsrcdir):
- sys.path[0:0] = [os.path.join(topsrcdir, "build")]
- import mach_bootstrap
- return mach_bootstrap.bootstrap(topsrcdir)
-
-# Check whether the current directory is within a mach src or obj dir.
-for dir_path in ancestors(os.getcwd()):
- # If we find a "mozinfo.json" file, we are in the objdir.
- mozinfo_path = os.path.join(dir_path, "mozinfo.json")
- if os.path.isfile(mozinfo_path):
- import json
- info = json.load(open(mozinfo_path))
- if "mozconfig" in info and "MOZCONFIG" not in os.environ:
- # If the MOZCONFIG environment variable is not already set, set it
- # to the value from mozinfo.json. This will tell the build system
- # to look for a config file at the path in $MOZCONFIG rather than
- # its default locations.
- #
- # Note: subprocess requires native strings in os.environ Python
- # 2.7.2 and earlier on Windows.
- os.environ[b"MOZCONFIG"] = str(info["mozconfig"])
-
- if "topsrcdir" in info:
- # Continue searching for mach_bootstrap in the source directory.
- dir_path = info["topsrcdir"]
-
- # If we find the mach bootstrap module, we are in the srcdir.
- mach_path = os.path.join(dir_path, "build/mach_bootstrap.py")
- if os.path.isfile(mach_path):
- mach = load_mach(dir_path)
- sys.exit(mach.run(sys.argv[1:]))
-
-print("Could not run mach: No mach source directory found")
-sys.exit(1)
diff --git a/widget/xpwidgets/PuppetWidget.cpp b/widget/xpwidgets/PuppetWidget.cpp
index ddd6ae6cb767..dffa04b07c66 100644
--- a/widget/xpwidgets/PuppetWidget.cpp
+++ b/widget/xpwidgets/PuppetWidget.cpp
@@ -36,7 +36,7 @@ InvalidateRegion(nsIWidget* aWidget, const nsIntRegion& aRegion)
/*static*/ already_AddRefed
nsIWidget::CreatePuppetWidget(TabChild* aTabChild)
{
- NS_ABORT_IF_FALSE(nsIWidget::UsePuppetWidgets(),
+ NS_ABORT_IF_FALSE(!aTabChild || nsIWidget::UsePuppetWidgets(),
"PuppetWidgets not allowed in this configuration");
nsCOMPtr widget = new PuppetWidget(aTabChild);
diff --git a/xpfe/appshell/public/nsIAppShellService.idl b/xpfe/appshell/public/nsIAppShellService.idl
index f73bfd42b158..c29483c2cc2a 100644
--- a/xpfe/appshell/public/nsIAppShellService.idl
+++ b/xpfe/appshell/public/nsIAppShellService.idl
@@ -6,6 +6,7 @@
#include "nsISupports.idl"
interface nsIXULWindow;
+interface nsIWebNavigation;
interface nsIURI;
interface nsIDOMWindow;
interface nsIAppShell;
@@ -43,6 +44,8 @@ interface nsIAppShellService : nsISupports
in long aInitialWidth,
in long aInitialHeight);
+ nsIWebNavigation createWindowlessBrowser();
+
[noscript]
void createHiddenWindow();
diff --git a/xpfe/appshell/src/nsAppShellService.cpp b/xpfe/appshell/src/nsAppShellService.cpp
index 4511534ee038..7aebfcdb0bf5 100644
--- a/xpfe/appshell/src/nsAppShellService.cpp
+++ b/xpfe/appshell/src/nsAppShellService.cpp
@@ -46,6 +46,10 @@
#include "mozilla/Preferences.h"
#include "mozilla/StartupTimeline.h"
+#include "nsEmbedCID.h"
+#include "nsIWebBrowser.h"
+#include "nsIDocShell.h"
+
using namespace mozilla;
// Default URL for the hidden window, can be overridden by a pref on Mac
@@ -203,6 +207,162 @@ nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent,
return rv;
}
+/*
+ * This class provides a stub implementation of nsIWebBrowserChrome2, as needed
+ * by nsAppShellService::CreateWindowlessBrowser
+ */
+class WebBrowserChrome2Stub : public nsIWebBrowserChrome2,
+ public nsIInterfaceRequestor {
+public:
+ virtual ~WebBrowserChrome2Stub() {}
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWEBBROWSERCHROME
+ NS_DECL_NSIWEBBROWSERCHROME2
+ NS_DECL_NSIINTERFACEREQUESTOR
+};
+
+NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
+ NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
+ NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
+ NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(WebBrowserChrome2Stub)
+NS_IMPL_RELEASE(WebBrowserChrome2Stub)
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::SetStatus(uint32_t aStatusType, const PRUnichar* aStatus)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::GetWebBrowser(nsIWebBrowser** aWebBrowser)
+{
+ NS_NOTREACHED("WebBrowserChrome2Stub::GetWebBrowser is not supported");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::SetWebBrowser(nsIWebBrowser* aWebBrowser)
+{
+ NS_NOTREACHED("WebBrowserChrome2Stub::SetWebBrowser is not supported");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::GetChromeFlags(uint32_t* aChromeFlags)
+{
+ *aChromeFlags = 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::SetChromeFlags(uint32_t aChromeFlags)
+{
+ NS_NOTREACHED("WebBrowserChrome2Stub::SetChromeFlags is not supported");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::DestroyBrowserWindow()
+{
+ NS_NOTREACHED("WebBrowserChrome2Stub::DestroyBrowserWindow is not supported");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::SizeBrowserTo(int32_t aCX, int32_t aCY)
+{
+ NS_NOTREACHED("WebBrowserChrome2Stub::SizeBrowserTo is not supported");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::ShowAsModal()
+{
+ NS_NOTREACHED("WebBrowserChrome2Stub::ShowAsModal is not supported");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::IsWindowModal(bool* aResult)
+{
+ *aResult = false;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::ExitModalEventLoop(nsresult aStatus)
+{
+ NS_NOTREACHED("WebBrowserChrome2Stub::ExitModalEventLoop is not supported");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::SetStatusWithContext(uint32_t aStatusType,
+ const nsAString& aStatusText,
+ nsISupports* aStatusContext)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+WebBrowserChrome2Stub::GetInterface(const nsIID & aIID, void **aSink)
+{
+ return QueryInterface(aIID, aSink);
+}
+
+NS_IMETHODIMP
+nsAppShellService::CreateWindowlessBrowser(nsIWebNavigation **aResult)
+{
+ /* First, we create an instance of nsWebBrowser. Instances of this class have
+ * an associated doc shell, which is what we're interested in.
+ */
+ nsCOMPtr browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
+ if (!browser) {
+ NS_ERROR("Couldn't create instance of nsWebBrowser!");
+ return NS_ERROR_FAILURE;
+ }
+
+ /* Next, we set the container window for our instance of nsWebBrowser. Since
+ * we don't actually have a window, we instead set the container window to be
+ * an instance of WebBrowserChrome2Stub, which provides a stub implementation
+ * of nsIWebBrowserChrome2.
+ */
+ nsRefPtr stub = new WebBrowserChrome2Stub();
+ if (!stub) {
+ NS_ERROR("Couldn't create instance of WebBrowserChrome2Stub!");
+ return NS_ERROR_FAILURE;
+ }
+ browser->SetContainerWindow(stub);
+
+ nsCOMPtr navigation = do_QueryInterface(browser);
+
+ nsCOMPtr item = do_QueryInterface(navigation);
+ item->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
+
+ /* A windowless web browser doesn't have an associated OS level window. To
+ * accomplish this, we initialize the window associated with our instance of
+ * nsWebBrowser with an instance of PuppetWidget, which provides a stub
+ * implementation of nsIWidget.
+ */
+ nsCOMPtr widget = nsIWidget::CreatePuppetWidget(nullptr);
+ if (!widget) {
+ NS_ERROR("Couldn't create instance of PuppetWidget");
+ return NS_ERROR_FAILURE;
+ }
+ widget->Create(nullptr, 0, nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)),
+ nullptr, nullptr);
+ nsCOMPtr window = do_QueryInterface(navigation);
+ window->InitWindow(0, widget, 0, 0, 0, 0);
+ window->Create();
+
+ navigation.forget(aResult);
+ return NS_OK;
+}
+
uint32_t
nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent,
uint32_t aChromeMask)