mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Fix bug 277724 -- make <select>, <textarea>, <button> restore disabled state. r+sr=jst
This commit is contained in:
parent
195cfecbbe
commit
91f9d8f94c
@ -58,6 +58,8 @@
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsPresState.h"
|
||||
#include "nsLayoutErrors.h"
|
||||
|
||||
#define NS_IN_SUBMIT_CLICK (1 << 0)
|
||||
|
||||
@ -92,12 +94,20 @@ public:
|
||||
NS_IMETHOD Click();
|
||||
NS_IMETHOD SetType(const nsAString& aType);
|
||||
|
||||
// overrided nsIFormControl method
|
||||
// overriden nsIFormControl methods
|
||||
NS_IMETHOD_(PRInt32) GetType() const { return mType; }
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
NS_IMETHOD SaveState();
|
||||
PRBool RestoreState(nsPresState* aState);
|
||||
|
||||
/**
|
||||
* Called when an attribute is about to be changed
|
||||
*/
|
||||
virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify);
|
||||
|
||||
// nsIContent overrides...
|
||||
virtual void SetFocus(nsPresContext* aPresContext);
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
@ -109,10 +119,12 @@ public:
|
||||
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
virtual void DoneCreatingElement();
|
||||
|
||||
protected:
|
||||
PRInt8 mType;
|
||||
PRPackedBool mHandlingClick;
|
||||
PRPackedBool mDisabledChanged;
|
||||
|
||||
private:
|
||||
// The analogue of defaultValue in the DOM for input and textarea
|
||||
@ -128,10 +140,11 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(Button)
|
||||
|
||||
|
||||
nsHTMLButtonElement::nsHTMLButtonElement(nsINodeInfo *aNodeInfo)
|
||||
: nsGenericHTMLFormElement(aNodeInfo)
|
||||
: nsGenericHTMLFormElement(aNodeInfo),
|
||||
mType(NS_FORM_BUTTON_SUBMIT), // default
|
||||
mHandlingClick(PR_FALSE),
|
||||
mDisabledChanged(PR_FALSE)
|
||||
{
|
||||
mType = NS_FORM_BUTTON_SUBMIT; // default
|
||||
mHandlingClick = PR_FALSE;
|
||||
}
|
||||
|
||||
nsHTMLButtonElement::~nsHTMLButtonElement()
|
||||
@ -565,3 +578,62 @@ nsHTMLButtonElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLButtonElement::DoneCreatingElement()
|
||||
{
|
||||
// Restore state as needed.
|
||||
RestoreFormControlState(this, this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLButtonElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify)
|
||||
{
|
||||
if (aNotify && aName == nsHTMLAtoms::disabled &&
|
||||
aNameSpaceID == kNameSpaceID_None) {
|
||||
mDisabledChanged = PR_TRUE;
|
||||
}
|
||||
|
||||
return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
|
||||
aValue, aNotify);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLButtonElement::SaveState()
|
||||
{
|
||||
if (!mDisabledChanged) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPresState *state = nsnull;
|
||||
nsresult rv = GetPrimaryPresState(this, &state);
|
||||
if (state) {
|
||||
PRBool disabled;
|
||||
GetDisabled(&disabled);
|
||||
if (disabled) {
|
||||
rv |= state->SetStateProperty(NS_LITERAL_STRING("disabled"),
|
||||
NS_LITERAL_STRING("t"));
|
||||
} else {
|
||||
rv |= state->SetStateProperty(NS_LITERAL_STRING("disabled"),
|
||||
NS_LITERAL_STRING("f"));
|
||||
}
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "disabled save failed!");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLButtonElement::RestoreState(nsPresState* aState)
|
||||
{
|
||||
nsAutoString disabled;
|
||||
nsresult rv =
|
||||
aState->GetStateProperty(NS_LITERAL_STRING("disabled"), disabled);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "disabled restore failed!");
|
||||
if (rv == NS_STATE_PROPERTY_EXISTS) {
|
||||
SetDisabled(disabled.EqualsLiteral("t"));
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -73,6 +73,7 @@
|
||||
#include "nsPresState.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsCheapSets.h"
|
||||
#include "nsLayoutErrors.h"
|
||||
|
||||
// Notify/query select frame for selectedIndex
|
||||
#include "nsIDocument.h"
|
||||
@ -268,6 +269,11 @@ public:
|
||||
// nsISelectElement
|
||||
NS_DECL_NSISELECTELEMENT
|
||||
|
||||
/**
|
||||
* Called when an attribute is about to be changed
|
||||
*/
|
||||
virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify);
|
||||
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
||||
PRBool aNotify);
|
||||
|
||||
@ -455,7 +461,9 @@ protected:
|
||||
/** The options[] array */
|
||||
nsRefPtr<nsHTMLOptionCollection> mOptions;
|
||||
/** false if the parser is in the middle of adding children. */
|
||||
PRBool mIsDoneAddingChildren;
|
||||
PRPackedBool mIsDoneAddingChildren;
|
||||
/** true if our disabled state has changed from the default **/
|
||||
PRPackedBool mDisabledChanged;
|
||||
/** The number of non-options as children of the select */
|
||||
PRUint32 mNonOptionChildren;
|
||||
/** The number of optgroups anywhere under the select */
|
||||
@ -488,6 +496,7 @@ nsHTMLSelectElement::nsHTMLSelectElement(nsINodeInfo *aNodeInfo,
|
||||
: nsGenericHTMLFormElement(aNodeInfo),
|
||||
mOptions(new nsHTMLOptionCollection(this)),
|
||||
mIsDoneAddingChildren(!aFromParser),
|
||||
mDisabledChanged(PR_FALSE),
|
||||
mNonOptionChildren(0),
|
||||
mOptGroupCount(0),
|
||||
mSelectedIndex(-1)
|
||||
@ -1677,6 +1686,19 @@ nsHTMLSelectElement::SelectSomething()
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLSelectElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify)
|
||||
{
|
||||
if (aNotify && aName == nsHTMLAtoms::disabled &&
|
||||
aNameSpaceID == kNameSpaceID_None) {
|
||||
mDisabledChanged = PR_TRUE;
|
||||
}
|
||||
|
||||
return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
|
||||
aValue, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLSelectElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
||||
PRBool aNotify)
|
||||
@ -1867,6 +1889,19 @@ nsHTMLSelectElement::SaveState()
|
||||
rv = presState->SetStatePropertyAsSupports(NS_LITERAL_STRING("selecteditems"),
|
||||
state);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "selecteditems set failed!");
|
||||
|
||||
if (mDisabledChanged) {
|
||||
PRBool disabled;
|
||||
GetDisabled(&disabled);
|
||||
if (disabled) {
|
||||
rv |= presState->SetStateProperty(NS_LITERAL_STRING("disabled"),
|
||||
NS_LITERAL_STRING("t"));
|
||||
} else {
|
||||
rv |= presState->SetStateProperty(NS_LITERAL_STRING("disabled"),
|
||||
NS_LITERAL_STRING("f"));
|
||||
}
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "disabled save failed!");
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -1887,6 +1922,13 @@ nsHTMLSelectElement::RestoreState(nsPresState* aState)
|
||||
DispatchContentReset();
|
||||
}
|
||||
|
||||
nsAutoString disabled;
|
||||
rv = aState->GetStateProperty(NS_LITERAL_STRING("disabled"), disabled);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "disabled restore failed!");
|
||||
if (rv == NS_STATE_PROPERTY_EXISTS) {
|
||||
SetDisabled(disabled.EqualsLiteral("t"));
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsLayoutErrors.h"
|
||||
|
||||
static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
|
||||
|
||||
@ -143,6 +144,11 @@ public:
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
|
||||
/**
|
||||
* Called when an attribute is about to be changed
|
||||
*/
|
||||
virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify);
|
||||
protected:
|
||||
nsCOMPtr<nsIControllers> mControllers;
|
||||
/** The current value. This is null if the frame owns the value. */
|
||||
@ -154,7 +160,9 @@ protected:
|
||||
/** Whether or not we are done adding children (always PR_TRUE if not
|
||||
created by a parser */
|
||||
PRPackedBool mDoneAddingChildren;
|
||||
|
||||
/** Whether our disabled state has changed from the default **/
|
||||
PRPackedBool mDisabledChanged;
|
||||
|
||||
NS_IMETHOD SelectAll(nsPresContext* aPresContext);
|
||||
/**
|
||||
* Get the value, whether it is from the content or the frame.
|
||||
@ -180,7 +188,8 @@ nsHTMLTextAreaElement::nsHTMLTextAreaElement(nsINodeInfo *aNodeInfo,
|
||||
mValue(nsnull),
|
||||
mValueChanged(PR_FALSE),
|
||||
mHandlingSelect(PR_FALSE),
|
||||
mDoneAddingChildren(!aFromParser)
|
||||
mDoneAddingChildren(!aFromParser),
|
||||
mDisabledChanged(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
@ -852,8 +861,8 @@ nsHTMLTextAreaElement::SaveState()
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Only save if value != defaultValue (bug 62713)
|
||||
nsPresState *state = nsnull;
|
||||
if (mValueChanged) {
|
||||
nsPresState *state = nsnull;
|
||||
rv = GetPrimaryPresState(this, &state);
|
||||
if (state) {
|
||||
nsAutoString value;
|
||||
@ -869,6 +878,23 @@ nsHTMLTextAreaElement::SaveState()
|
||||
}
|
||||
}
|
||||
|
||||
if (mDisabledChanged) {
|
||||
if (!state) {
|
||||
rv = GetPrimaryPresState(this, &state);
|
||||
}
|
||||
if (state) {
|
||||
PRBool disabled;
|
||||
GetDisabled(&disabled);
|
||||
if (disabled) {
|
||||
rv |= state->SetStateProperty(NS_LITERAL_STRING("disabled"),
|
||||
NS_LITERAL_STRING("t"));
|
||||
} else {
|
||||
rv |= state->SetStateProperty(NS_LITERAL_STRING("disabled"),
|
||||
NS_LITERAL_STRING("f"));
|
||||
}
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "disabled save failed!");
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -876,12 +902,30 @@ PRBool
|
||||
nsHTMLTextAreaElement::RestoreState(nsPresState* aState)
|
||||
{
|
||||
nsAutoString value;
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
aState->GetStateProperty(NS_LITERAL_STRING("value"), value);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "value restore failed!");
|
||||
SetValue(value);
|
||||
|
||||
nsAutoString disabled;
|
||||
rv = aState->GetStateProperty(NS_LITERAL_STRING("disabled"), disabled);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "disabled restore failed!");
|
||||
if (rv == NS_STATE_PROPERTY_EXISTS) {
|
||||
SetDisabled(disabled.EqualsLiteral("t"));
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLTextAreaElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify)
|
||||
{
|
||||
if (aNotify && aName == nsHTMLAtoms::disabled &&
|
||||
aNameSpaceID == kNameSpaceID_None) {
|
||||
mDisabledChanged = PR_TRUE;
|
||||
}
|
||||
|
||||
return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
|
||||
aValue, aNotify);
|
||||
}
|
||||
|
@ -1126,6 +1126,10 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
|
||||
}
|
||||
break;
|
||||
|
||||
case eHTMLTag_button:
|
||||
content->DoneCreatingElement();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1349,7 +1353,6 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
|
||||
break;
|
||||
|
||||
case eHTMLTag_input:
|
||||
case eHTMLTag_button:
|
||||
content->DoneCreatingElement();
|
||||
|
||||
break;
|
||||
|
28
testing/mochitest/static/bug277724_iframe1.html
Normal file
28
testing/mochitest/static/bug277724_iframe1.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!-- Use an unload handler to prevent bfcache from messing with us -->
|
||||
<body onunload="parent.childUnloaded = true;">
|
||||
<select id="select">
|
||||
<option>aaa</option>
|
||||
<option>bbbb</option>
|
||||
</select>
|
||||
|
||||
<textarea id="textarea">
|
||||
</textarea>
|
||||
|
||||
<input type="text" id="text">
|
||||
<input type="password" id="password">
|
||||
<input type="checkbox" id="checkbox">
|
||||
<input type="radio" id="radio">
|
||||
<input type="image" id="image">
|
||||
<input type="submit" id="submit">
|
||||
<input type="reset" id="reset">
|
||||
<input type="button" id="button input">
|
||||
<input type="hidden" id="hidden">
|
||||
<input type="file" id="file">
|
||||
|
||||
<button type="submit" id="submit button"></button>
|
||||
<button type="reset" id="reset button"></button>
|
||||
<button type="button" id="button"></button>
|
||||
</body>
|
||||
</html>
|
27
testing/mochitest/static/bug277724_iframe2.xhtml
Normal file
27
testing/mochitest/static/bug277724_iframe2.xhtml
Normal file
@ -0,0 +1,27 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!-- Use an unload handler to prevent bfcache from messing with us -->
|
||||
<body onunload="parent.childUnloaded = true;">
|
||||
<select id="select">
|
||||
<option>aaa</option>
|
||||
<option>bbbb</option>
|
||||
</select>
|
||||
|
||||
<textarea id="textarea">
|
||||
</textarea>
|
||||
|
||||
<input type="text" id="text" />
|
||||
<input type="password" id="password" />
|
||||
<input type="checkbox" id="checkbox" />
|
||||
<input type="radio" id="radio" />
|
||||
<input type="image" id="image" />
|
||||
<input type="submit" id="submit" />
|
||||
<input type="reset" id="reset" />
|
||||
<input type="button" id="button input" />
|
||||
<input type="hidden" id="hidden" />
|
||||
<input type="file" id="file" />
|
||||
|
||||
<button type="submit" id="submit button"></button>
|
||||
<button type="reset" id="reset button"></button>
|
||||
<button type="button" id="button"></button>
|
||||
</body>
|
||||
</html>
|
@ -62,6 +62,7 @@ RunSet.runall = function() {
|
||||
'test_bug100533.html',
|
||||
'test_bug218277.html',
|
||||
'test_bug237071.html',
|
||||
'test_bug277724.html',
|
||||
'test_bug302186.html',
|
||||
'test_bug308856.html',
|
||||
'test_bug333983.html',
|
||||
|
138
testing/mochitest/tests/test_bug277724.html
Normal file
138
testing/mochitest/tests/test_bug277724.html
Normal file
@ -0,0 +1,138 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=277724
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 277724</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.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=277724">Mozilla Bug 277724</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 277724 **/
|
||||
|
||||
var childUnloaded = false;
|
||||
|
||||
var nodes = [
|
||||
[ "select", HTMLSelectElement ],
|
||||
[ "textarea", HTMLTextAreaElement ],
|
||||
[ "text", HTMLInputElement ],
|
||||
[ "password", HTMLInputElement ],
|
||||
[ "checkbox", HTMLInputElement ],
|
||||
[ "radio", HTMLInputElement ],
|
||||
[ "image", HTMLInputElement ],
|
||||
[ "submit", HTMLInputElement ],
|
||||
[ "reset", HTMLInputElement ],
|
||||
[ "button input", HTMLInputElement ],
|
||||
[ "hidden", HTMLInputElement ],
|
||||
[ "file", HTMLInputElement ],
|
||||
[ "submit button", HTMLButtonElement ],
|
||||
[ "reset button", HTMLButtonElement ],
|
||||
[ "button", HTMLButtonElement ]
|
||||
];
|
||||
|
||||
function startTest(frameid) {
|
||||
is(childUnloaded, false, "Child not unloaded yet");
|
||||
|
||||
var doc = $(frameid).contentDocument;
|
||||
ok(doc instanceof Document, "Check for doc", "doc should be a document");
|
||||
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
var id = nodes[i][0];
|
||||
var node = doc.getElementById(id);
|
||||
ok(node instanceof nodes[i][1],
|
||||
"Check for " + id, id + " should be a " + nodes[i][1]);
|
||||
is(node.disabled, false, "check for " + id + " state");
|
||||
node.disabled = true;
|
||||
is(node.disabled, true, "check for " + id + " state change");
|
||||
}
|
||||
|
||||
$(frameid).onload = function () { continueTest(frameid) };
|
||||
|
||||
// Do this off a timeout so it's not treated like a replace load.
|
||||
function loadBlank() {
|
||||
$(frameid).contentWindow.location = "about:blank";
|
||||
}
|
||||
setTimeout(loadBlank, 0);
|
||||
}
|
||||
|
||||
function continueTest(frameid) {
|
||||
is(childUnloaded, true, "Unload handler should have fired");
|
||||
var doc = $(frameid).contentDocument;
|
||||
ok(doc instanceof Document, "Check for doc", "doc should be a document");
|
||||
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
var id = nodes[i][0];
|
||||
var node = doc.getElementById(id);
|
||||
ok(node === null,
|
||||
"Check for " + id, id + " should be null");
|
||||
}
|
||||
|
||||
$(frameid).onload = function() { finishTest(frameid) };
|
||||
|
||||
// Do this off a timeout too. Why, I'm not sure. Something in session
|
||||
// history creates another history state if we don't. :(
|
||||
function goBack() {
|
||||
$(frameid).contentWindow.history.back();
|
||||
}
|
||||
setTimeout(goBack, 0);
|
||||
}
|
||||
|
||||
// XXXbz this is a nasty hack to work around the XML content sink not being
|
||||
// incremental, so that the _first_ control we test is ok but others are not.
|
||||
var testIs = is;
|
||||
var once = false;
|
||||
function flipper(a, b, c) {
|
||||
if (once) {
|
||||
todo(a == b, c);
|
||||
} else {
|
||||
once = true;
|
||||
is(a, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
function finishTest(frameid) {
|
||||
var doc = $(frameid).contentDocument;
|
||||
ok(doc instanceof Document, "Check for doc", "doc should be a document");
|
||||
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
var id = nodes[i][0];
|
||||
var node = doc.getElementById(id);
|
||||
ok(node instanceof nodes[i][1],
|
||||
"Check for " + id, id + " should be a " + nodes[i][1]);
|
||||
testIs(node.disabled, true, "check for " + id + " state restore");
|
||||
}
|
||||
|
||||
if (frameid == "frame2") {
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
childUnloaded = false;
|
||||
|
||||
// XXXbz this is a nasty hack to deal with the content sink. See above.
|
||||
testIs = flipper;
|
||||
|
||||
$("frame2").onload = function () { startTest("frame2") };
|
||||
$("frame2").src = "/static/bug277724_iframe2.xhtml";
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
<!-- Don't use display:none, since we don't support framestate restoration
|
||||
without a frame tree -->
|
||||
<div id="content" style="visibility: hidden">
|
||||
<iframe src="/static/bug277724_iframe1.html" id="frame1"
|
||||
onload="startTest('frame1')"></iframe>
|
||||
<iframe src="" id="frame2"></iframe>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user