Bug 846906 - Implement nsAppShellService::CreateWindowlessBrowser; r=bz; sr=benjamin
This commit is contained in:
@@ -97,6 +97,7 @@ MOCHITEST_CHROME_FILES = \
|
|||||||
test_private_hidden_window.html \
|
test_private_hidden_window.html \
|
||||||
docshell_helpers.js \
|
docshell_helpers.js \
|
||||||
generic.html \
|
generic.html \
|
||||||
|
test_bug846906.xul \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
||||||
|
|||||||
78
docshell/test/chrome/test_bug846906.xul
Normal file
78
docshell/test/chrome/test_bug846906.xul
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||||
|
<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=846906
|
||||||
|
-->
|
||||||
|
<window title="Mozilla Bug 846906"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
|
||||||
|
<title>Test for Bug 846906</title>
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
|
||||||
|
<!-- test code goes here -->
|
||||||
|
<script type="application/javascript">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
/** Test for Bug 846906 **/
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
var appShellService = Components.classes["@mozilla.org/appshell/appShellService;1"]
|
||||||
|
.getService(Components.interfaces.nsIAppShellService);
|
||||||
|
ok(appShellService, "Should be able to get app shell service");
|
||||||
|
|
||||||
|
var webNavigation = appShellService.createWindowlessBrowser();
|
||||||
|
ok(webNavigation, "Should be able to create windowless browser");
|
||||||
|
|
||||||
|
var interfaceRequestor = webNavigation.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
|
||||||
|
ok(interfaceRequestor, "Should be able to query interface requestor interface");
|
||||||
|
|
||||||
|
var docShell = interfaceRequestor.getInterface(Components.interfaces.nsIDocShell);
|
||||||
|
ok(docShell, "Should be able to get doc shell interface");
|
||||||
|
|
||||||
|
var webNavigation = docShell.QueryInterface(Components.interfaces.nsIWebNavigation);
|
||||||
|
ok(webNavigation, "Should be able to query web navigation interface");
|
||||||
|
|
||||||
|
var document = webNavigation.document;
|
||||||
|
ok(document, "Should be able to get document");
|
||||||
|
|
||||||
|
var iframe = document.createElement("iframe");
|
||||||
|
ok(iframe, "Should be able to create iframe");
|
||||||
|
|
||||||
|
iframe.onload = function () {
|
||||||
|
ok(true, "Should receive initial onload event");
|
||||||
|
|
||||||
|
iframe.onload = function () {
|
||||||
|
ok(true, "Should receive onload event");
|
||||||
|
|
||||||
|
var contentDocument = iframe.contentDocument;
|
||||||
|
ok(contentDocument, "Should be able to get content document");
|
||||||
|
|
||||||
|
var div = contentDocument.getElementById("div1");
|
||||||
|
ok(div, "Should be able to get element by id");
|
||||||
|
|
||||||
|
var rect = div.getBoundingClientRect();
|
||||||
|
ok(rect, "Should be able to get bounding client rect");
|
||||||
|
|
||||||
|
// xxx: can we do better than hardcoding these values here?
|
||||||
|
ok(rect.left == 8);
|
||||||
|
ok(rect.right == 477);
|
||||||
|
ok(rect.top == 8);
|
||||||
|
ok(rect.bottom == 1010);
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
};
|
||||||
|
iframe.setAttribute("src", "http://mochi.test:8888/chrome/docshell/test/chrome/generic.html");
|
||||||
|
};
|
||||||
|
document.documentElement.appendChild(iframe);
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- test results are displayed in the html:body -->
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=846906"
|
||||||
|
target="_blank">Mozilla Bug 846906</a>
|
||||||
|
</body>
|
||||||
|
</window>
|
||||||
51
mach
51
mach
@@ -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)
|
|
||||||
@@ -36,7 +36,7 @@ InvalidateRegion(nsIWidget* aWidget, const nsIntRegion& aRegion)
|
|||||||
/*static*/ already_AddRefed<nsIWidget>
|
/*static*/ already_AddRefed<nsIWidget>
|
||||||
nsIWidget::CreatePuppetWidget(TabChild* aTabChild)
|
nsIWidget::CreatePuppetWidget(TabChild* aTabChild)
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(nsIWidget::UsePuppetWidgets(),
|
NS_ABORT_IF_FALSE(!aTabChild || nsIWidget::UsePuppetWidgets(),
|
||||||
"PuppetWidgets not allowed in this configuration");
|
"PuppetWidgets not allowed in this configuration");
|
||||||
|
|
||||||
nsCOMPtr<nsIWidget> widget = new PuppetWidget(aTabChild);
|
nsCOMPtr<nsIWidget> widget = new PuppetWidget(aTabChild);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
|
|
||||||
interface nsIXULWindow;
|
interface nsIXULWindow;
|
||||||
|
interface nsIWebNavigation;
|
||||||
interface nsIURI;
|
interface nsIURI;
|
||||||
interface nsIDOMWindow;
|
interface nsIDOMWindow;
|
||||||
interface nsIAppShell;
|
interface nsIAppShell;
|
||||||
@@ -43,6 +44,8 @@ interface nsIAppShellService : nsISupports
|
|||||||
in long aInitialWidth,
|
in long aInitialWidth,
|
||||||
in long aInitialHeight);
|
in long aInitialHeight);
|
||||||
|
|
||||||
|
nsIWebNavigation createWindowlessBrowser();
|
||||||
|
|
||||||
[noscript]
|
[noscript]
|
||||||
void createHiddenWindow();
|
void createHiddenWindow();
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,10 @@
|
|||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/StartupTimeline.h"
|
#include "mozilla/StartupTimeline.h"
|
||||||
|
|
||||||
|
#include "nsEmbedCID.h"
|
||||||
|
#include "nsIWebBrowser.h"
|
||||||
|
#include "nsIDocShell.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
// Default URL for the hidden window, can be overridden by a pref on Mac
|
// Default URL for the hidden window, can be overridden by a pref on Mac
|
||||||
@@ -203,6 +207,162 @@ nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent,
|
|||||||
return rv;
|
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<nsIWebBrowser> 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<WebBrowserChrome2Stub> stub = new WebBrowserChrome2Stub();
|
||||||
|
if (!stub) {
|
||||||
|
NS_ERROR("Couldn't create instance of WebBrowserChrome2Stub!");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
browser->SetContainerWindow(stub);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWebNavigation> navigation = do_QueryInterface(browser);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocShellTreeItem> 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<nsIWidget> 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<nsIBaseWindow> window = do_QueryInterface(navigation);
|
||||||
|
window->InitWindow(0, widget, 0, 0, 0, 0);
|
||||||
|
window->Create();
|
||||||
|
|
||||||
|
navigation.forget(aResult);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent,
|
nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent,
|
||||||
uint32_t aChromeMask)
|
uint32_t aChromeMask)
|
||||||
|
|||||||
Reference in New Issue
Block a user