Bug 449781. Toggling display on a subframe shouldn't give the subframe's document the same device context as the parent document. r=roc, sr=jst

This commit is contained in:
Boris Zbarsky 2008-08-18 15:22:19 -04:00
Родитель b093ac751d
Коммит 176a0e0d6f
7 изменённых файлов: 154 добавлений и 27 удалений

Просмотреть файл

@ -192,7 +192,6 @@
#include "nsPluginError.h"
static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
@ -6389,16 +6388,9 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
nsCOMPtr<nsIWidget> widget;
NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(widget)), NS_ERROR_FAILURE);
nsCOMPtr<nsIDeviceContext> deviceContext;
if (widget) {
deviceContext = do_CreateInstance(kDeviceContextCID);
NS_ENSURE_TRUE(deviceContext, NS_ERROR_FAILURE);
deviceContext->Init(widget->GetNativeData(NS_NATIVE_WIDGET));
}
nsRect bounds(x, y, cx, cy);
if (NS_FAILED(mContentViewer->Init(widget, deviceContext, bounds))) {
if (NS_FAILED(mContentViewer->Init(widget, bounds))) {
mContentViewer = nsnull;
NS_ERROR("ContentViewer Initialization failed");
return NS_ERROR_FAILURE;

Просмотреть файл

@ -7,20 +7,17 @@ interface nsIPrintSettings;
%{ C++
class nsIWidget;
class nsIDeviceContext;
struct nsRect;
%}
[ptr] native nsIWidgetPtr(nsIWidget);
[ptr] native nsIDeviceContextPtr(nsIDeviceContext);
[ref] native nsRectRef(nsRect);
[scriptable, uuid(89653afe-182f-401f-9f3c-8858d91387cd)]
[scriptable, uuid(05b290ac-d880-4900-bb1f-2211b5f8accc)]
interface nsIContentViewer : nsISupports
{
[noscript] void init(in nsIWidgetPtr aParentWidget,
in nsIDeviceContextPtr aDeviceContext,
[const] in nsRectRef aBounds);
attribute nsISupports container;

Просмотреть файл

@ -357,9 +357,17 @@ private:
* @param aSize the initial size in appunits
*/
nsresult MakeWindow(const nsSize& aSize);
/**
* Create our device context
*/
nsresult CreateDeviceContext(nsIWidget* aWidget);
/**
* Make sure to set up mDeviceContext as needed before calling this
*/
nsresult InitInternal(nsIWidget* aParentWidget,
nsISupports *aState,
nsIDeviceContext* aDeviceContext,
const nsRect& aBounds,
PRBool aDoCreation,
PRBool aInPrintPreview,
@ -407,7 +415,7 @@ protected:
// class, please make the ownership explicit (pinkerton, scc).
nsWeakPtr mContainer; // it owns me!
nsCOMPtr<nsIDeviceContext> mDeviceContext; // ??? can't hurt, but...
nsCOMPtr<nsIDeviceContext> mDeviceContext; // We create and own this baby
// the following six items are explicitly in this order
// so they will be destroyed in the reverse order (pinkerton, scc)
@ -480,6 +488,7 @@ protected:
// Class IDs
static NS_DEFINE_CID(kViewManagerCID, NS_VIEW_MANAGER_CID);
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
static NS_DEFINE_CID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
//------------------------------------------------------------------
nsresult
@ -657,10 +666,12 @@ DocumentViewerImpl::GetContainer(nsISupports** aResult)
NS_IMETHODIMP
DocumentViewerImpl::Init(nsIWidget* aParentWidget,
nsIDeviceContext* aDeviceContext,
const nsRect& aBounds)
{
return InitInternal(aParentWidget, nsnull, aDeviceContext, aBounds, PR_TRUE, PR_FALSE);
nsresult rv = CreateDeviceContext(aParentWidget);
NS_ENSURE_SUCCESS(rv, rv);
return InitInternal(aParentWidget, nsnull, aBounds, PR_TRUE, PR_FALSE);
}
nsresult
@ -794,7 +805,6 @@ DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReena
nsresult
DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
nsISupports *aState,
nsIDeviceContext* aDeviceContext,
const nsRect& aBounds,
PRBool aDoCreation,
PRBool aInPrintPreview,
@ -805,8 +815,6 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
nsresult rv = NS_OK;
NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER);
mDeviceContext = aDeviceContext;
PRBool makeCX = PR_FALSE;
if (aDoCreation) {
if (aParentWidget && !mPresContext) {
@ -819,7 +827,7 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
new nsPresContext(mDocument, nsPresContext::eContext_Galley);
NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = mPresContext->Init(aDeviceContext);
nsresult rv = mPresContext->Init(mDeviceContext);
if (NS_FAILED(rv)) {
mPresContext = nsnull;
return rv;
@ -1242,8 +1250,7 @@ DocumentViewerImpl::Open(nsISupports *aState, nsISHEntry *aSHEntry)
nsRect bounds;
mWindow->GetBounds(bounds);
nsresult rv = InitInternal(mParentWidget, aState, mDeviceContext, bounds,
PR_FALSE, PR_FALSE);
nsresult rv = InitInternal(mParentWidget, aState, bounds, PR_FALSE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
if (mDocument)
@ -1872,8 +1879,6 @@ DocumentViewerImpl::Show(void)
}
if (mDocument && !mPresShell && !mWindow) {
nsresult rv;
nsCOMPtr<nsIBaseWindow> base_win(do_QueryReferent(mContainer));
NS_ENSURE_TRUE(base_win, NS_ERROR_UNEXPECTED);
@ -1881,7 +1886,8 @@ DocumentViewerImpl::Show(void)
NS_ENSURE_TRUE(mParentWidget, NS_ERROR_UNEXPECTED);
mParentWidget->Release(); // GetParentWidget AddRefs, but mParentWidget is weak
mDeviceContext = mParentWidget->GetDeviceContext();
nsresult rv = CreateDeviceContext(mParentWidget);
NS_ENSURE_SUCCESS(rv, rv);
// Create presentation context
NS_ASSERTION(!mPresContext, "Shouldn't have a prescontext if we have no shell!");
@ -2271,6 +2277,18 @@ DocumentViewerImpl::MakeWindow(const nsSize& aSize)
return rv;
}
nsresult
DocumentViewerImpl::CreateDeviceContext(nsIWidget* aWidget)
{
NS_PRECONDITION(!mDeviceContext, "How come we're calling this?");
if (aWidget) {
mDeviceContext = do_CreateInstance(kDeviceContextCID);
NS_ENSURE_TRUE(mDeviceContext, NS_ERROR_FAILURE);
mDeviceContext->Init(aWidget->GetNativeData(NS_NATIVE_WIDGET));
}
return NS_OK;
}
// Return the selection for the document. Note that text fields have their
// own selection, which cannot be accessed with this method. Use
// mPresShell->GetSelectionForCopy() instead.
@ -4105,7 +4123,7 @@ NS_IMETHODIMP DocumentViewerImpl::SetPageMode(PRBool aPageMode, nsIPrintSettings
nsresult rv = mPresContext->Init(mDeviceContext);
NS_ENSURE_SUCCESS(rv, rv);
}
InitInternal(mParentWidget, nsnull, mDeviceContext, bounds, PR_TRUE, PR_FALSE, PR_FALSE);
InitInternal(mParentWidget, nsnull, bounds, PR_TRUE, PR_FALSE, PR_FALSE);
mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC);
Show();

Просмотреть файл

@ -93,6 +93,7 @@ _TEST_FILES = \
test_bug420499.xul \
test_bug423523.html \
test_bug445810.html \
test_bug449781.html \
$(NULL)
# test_bug396024.html is currently disabled because it interacts badly with
# the "You can't print-preview while the page is loading" dialog.

Просмотреть файл

@ -0,0 +1,71 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=449781
-->
<head>
<title>Test for Bug 449781</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=449781">Mozilla Bug 449781</a>
<p id="display">Canary</p>
<iframe src="about:blank" id="ourFrame" style="visibility: hidden">
</iframe>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var s1, s2, s3, s4;
/** Test for Bug 449781 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
s1 = snapshotWindow(window);
$("ourFrame").style.display = "none";
is($("ourFrame").offsetWidth, 0, "Unexpected width after hiding");
$("ourFrame").style.display = "";
is($("ourFrame").clientWidth, 300, "Unexpected width after showing");
s2 = snapshotWindow(window);
var equal, str1, str2;
[equal, str1, str2] = compareSnapshots(s1, s2);
ok(equal, "Show/hide should have no effect",
"got " + str1 + " but expected " + str2);
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var viewer =
$("ourFrame").contentWindow
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell)
.contentViewer
.QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
viewer.fullZoom = 2;
s3 = snapshotWindow(window);
[equal, str1, str2] = compareSnapshots(s1, s3);
ok(equal, "Zoom should have no effect",
"got " + str1 + " but expected " + str2);
$("display").style.display = "none";
s4 = snapshotWindow(window);
[equal, str1, str2] = compareSnapshots(s3, s4);
ok(!equal, "Should be able to see the canary");
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -51,6 +51,7 @@ _SIMPLETEST_FILES = MozillaFileLogger.js \
TestRunner.js \
setup.js \
EventUtils.js \
WindowSnapshot.js \
$(NULL)
libs:: $(_SIMPLETEST_FILES)

Просмотреть файл

@ -0,0 +1,47 @@
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var gWindowSnapshotCompareHelper;
try {
gWindowSnapshotCompareHelper =
Components.classes["@mozilla.org/reftest-helper;1"]
.getService(Components.interfaces.nsIReftestHelper);
} catch (e) {
gWindowSnapshotCompareHelper = null;
}
function snapshotWindow(win) {
var el = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
el.width = win.innerWidth;
el.height = win.innerHeight;
// drawWindow requires privileges
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
el.getContext("2d").drawWindow(win, win.scrollX, win.scrollY,
win.innerWidth, win.innerHeight,
"rgb(255,255,255)");
return el;
}
// If the two snapshots aren't equal, returns their serializations as data URIs.
function compareSnapshots(s1, s2) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var s1Str, s2Str;
var equal = false;
if (gWindowSnapshotCompareHelper) {
equal = (gWindowSnapshotCompareHelper.compareCanvas(s1, s2) == 0);
}
if (!equal) {
s1Str = s1.toDataURL();
s2Str = s2.toDataURL();
if (!gWindowSnapshotCompareHelper) {
equal = (s1Str == s2Str);
}
}
return [equal, s1Str, s2Str];
}