Bug 846906 - Implement nsAppShellService::CreateWindowlessBrowser; r=bz; sr=benjamin

This commit is contained in:
Eddy Bruel 2013-04-04 15:24:32 +02:00
parent f38d9e1c17
commit 740434ef83
5 changed files with 243 additions and 1 deletions

View File

@ -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)

View 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>

View File

@ -36,7 +36,7 @@ InvalidateRegion(nsIWidget* aWidget, const nsIntRegion& aRegion)
/*static*/ already_AddRefed<nsIWidget>
nsIWidget::CreatePuppetWidget(TabChild* aTabChild)
{
NS_ABORT_IF_FALSE(nsIWidget::UsePuppetWidgets(),
NS_ABORT_IF_FALSE(!aTabChild || nsIWidget::UsePuppetWidgets(),
"PuppetWidgets not allowed in this configuration");
nsCOMPtr<nsIWidget> widget = new PuppetWidget(aTabChild);

View File

@ -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();

View File

@ -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<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
nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent,
uint32_t aChromeMask)