зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1549560 - Move HTMLDocument.open/close/write/writeln to Document; r=farre
Differential Revision: https://phabricator.services.mozilla.com/D32388 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
0f77590986
Коммит
ad6a833e39
|
@ -95,7 +95,7 @@
|
|||
<keyset id="placesOrganizerKeyset">
|
||||
<!-- Instantiation Keys -->
|
||||
<key id="placesKey_close" key="&cmd.close.key;" modifiers="accel"
|
||||
oncommand="close();"/>
|
||||
oncommand="window.close();"/>
|
||||
|
||||
<!-- Command Keys -->
|
||||
<key id="placesKey_find:all"
|
||||
|
@ -247,7 +247,7 @@
|
|||
key="placesKey_close"
|
||||
label="&file.close.label;"
|
||||
accesskey="&file.close.accesskey;"
|
||||
oncommand="close();"/>
|
||||
oncommand="window.close();"/>
|
||||
#endif
|
||||
</menupopup>
|
||||
#ifdef XP_MACOSX
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
</vbox>
|
||||
|
||||
<hbox class="actionButtons" align="right" flex="1">
|
||||
<button oncommand="close();" icon="close"
|
||||
<button oncommand="window.close();" icon="close"
|
||||
data-l10n-id="blocklist-button-cancel"/>
|
||||
<button id="btnApplyChanges" oncommand="gBlocklistManager.onApplyChanges();" icon="save"
|
||||
data-l10n-id="blocklist-button-ok"/>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<spacer flex="1"/>
|
||||
<hbox class="actionButtons" align="right" flex="1">
|
||||
<button id="butCancel"
|
||||
oncommand="close(event);"
|
||||
oncommand="window.close(event);"
|
||||
class="syncDisconnectButton"
|
||||
data-l10n-id="sync-disconnect-cancel"/>
|
||||
<button id="butDisconnect"
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
|
||||
<separator class="thin"/>
|
||||
|
||||
<button oncommand="close();" icon="close" label="Close" />
|
||||
<button oncommand="window.close();" icon="close" label="Close" />
|
||||
|
||||
</dialog>
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
|
||||
<separator class="thin"/>
|
||||
|
||||
<button oncommand="close();" icon="close" label="Close" />
|
||||
<button oncommand="window.close();" icon="close" label="Close" />
|
||||
|
||||
</dialog>
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
</hbox>
|
||||
<spacer flex="1"/>
|
||||
<hbox class="actionButtons" align="right" flex="1">
|
||||
<button oncommand="close();" icon="close"
|
||||
<button oncommand="window.close();" icon="close"
|
||||
data-l10n-id="permissions-button-cancel" />
|
||||
<button id="btnApplyChanges" oncommand="gPermissionManager.onApplyChanges();" icon="save"
|
||||
data-l10n-id="permissions-button-ok" />
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
data-l10n-id="disable-extension"/>
|
||||
</hbox>
|
||||
<hbox class="actionButtons" align="right" flex="1">
|
||||
<button oncommand="close();" icon="close" id="cancel"
|
||||
<button oncommand="window.close();" icon="close" id="cancel"
|
||||
data-l10n-id="permissions-button-cancel" />
|
||||
<button id="btnApplyChanges" oncommand="gSitePermissionsManager.onApplyChanges();" icon="save"
|
||||
data-l10n-id="permissions-button-ok" />
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
icon="clear"
|
||||
oncommand="gTranslationExceptions.onAllSitesDeleted();"/>
|
||||
<spacer flex="1"/>
|
||||
<button oncommand="close();" icon="close"
|
||||
<button oncommand="window.close();" icon="close"
|
||||
data-l10n-id="translation-button-close"/>
|
||||
</hbox>
|
||||
</window>
|
||||
|
|
|
@ -313,12 +313,16 @@
|
|||
#include "StorageAccessPermissionRequest.h"
|
||||
#include "mozilla/dom/WindowProxyHolder.h"
|
||||
#include "ThirdPartyUtil.h"
|
||||
#include "nsHtml5Module.h"
|
||||
#include "nsHtml5Parser.h"
|
||||
|
||||
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
|
||||
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
|
||||
#define XML_DECLARATION_BITS_STANDALONE_EXISTS (1 << 2)
|
||||
#define XML_DECLARATION_BITS_STANDALONE_YES (1 << 3)
|
||||
|
||||
#define NS_MAX_DOCUMENT_WRITE_DEPTH 20
|
||||
|
||||
extern bool sDisablePrefetchHTTPSPref;
|
||||
|
||||
mozilla::LazyLogModule gPageCacheLog("PageCache");
|
||||
|
@ -1251,10 +1255,13 @@ Document::Document(const char* aContentType)
|
|||
mLoadEventFiring(false),
|
||||
mSkipLoadEventAfterClose(false),
|
||||
mDisableCookieAccess(false),
|
||||
mDisableDocWrite(false),
|
||||
mTooDeepWriteRecursion(false),
|
||||
mPendingFullscreenRequests(0),
|
||||
mXMLDeclarationBits(0),
|
||||
mOnloadBlockCount(0),
|
||||
mAsyncOnloadBlockCount(0),
|
||||
mWriteLevel(0),
|
||||
mCompatMode(eCompatibility_FullStandards),
|
||||
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
|
||||
mAncestorIsLoading(false),
|
||||
|
@ -2519,6 +2526,17 @@ void Document::CompatibilityModeChanged() {
|
|||
ApplicableStylesChanged();
|
||||
}
|
||||
|
||||
void Document::SetCompatibilityMode(nsCompatibility aMode) {
|
||||
NS_ASSERTION(IsHTMLDocument() || aMode == eCompatibility_FullStandards,
|
||||
"Bad compat mode for XHTML document!");
|
||||
|
||||
if (mCompatMode == aMode) {
|
||||
return;
|
||||
}
|
||||
mCompatMode = aMode;
|
||||
CompatibilityModeChanged();
|
||||
}
|
||||
|
||||
static void WarnIfSandboxIneffective(nsIDocShell* aDocShell,
|
||||
uint32_t aSandboxFlags,
|
||||
nsIChannel* aChannel) {
|
||||
|
@ -6709,6 +6727,485 @@ nsIHTMLCollection* Document::Anchors() {
|
|||
return mAnchors;
|
||||
}
|
||||
|
||||
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> Document::Open(
|
||||
const nsAString& aURL, const nsAString& aName, const nsAString& aFeatures,
|
||||
bool aReplace, ErrorResult& rv) {
|
||||
MOZ_ASSERT(nsContentUtils::CanCallerAccess(this),
|
||||
"XOW should have caught this!");
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = GetInnerWindow();
|
||||
if (!window) {
|
||||
rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindowOuter> outer =
|
||||
nsPIDOMWindowOuter::GetFromCurrentInner(window);
|
||||
if (!outer) {
|
||||
rv.Throw(NS_ERROR_NOT_INITIALIZED);
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<nsGlobalWindowOuter> win = nsGlobalWindowOuter::Cast(outer);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> newWindow;
|
||||
// XXXbz We ignore aReplace for now.
|
||||
rv = win->OpenJS(aURL, aName, aFeatures, getter_AddRefs(newWindow));
|
||||
if (!newWindow) {
|
||||
return nullptr;
|
||||
}
|
||||
return WindowProxyHolder(newWindow->GetBrowsingContext());
|
||||
}
|
||||
|
||||
Document* Document::Open(const Optional<nsAString>& /* unused */,
|
||||
const nsAString& /* unused */, ErrorResult& aError) {
|
||||
// Implements
|
||||
// <https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-open-steps>
|
||||
|
||||
MOZ_ASSERT(nsContentUtils::CanCallerAccess(this),
|
||||
"XOW should have caught this!");
|
||||
|
||||
// Step 1 -- throw if we're an XML document.
|
||||
if (!IsHTMLDocument() || mDisableDocWrite) {
|
||||
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 2 -- throw if dynamic markup insertion should throw.
|
||||
if (ShouldThrowOnDynamicMarkupInsertion()) {
|
||||
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 3 -- get the entry document, so we can use it for security checks.
|
||||
nsCOMPtr<Document> callerDoc = GetEntryDocument();
|
||||
if (!callerDoc) {
|
||||
// If we're called from C++ or in some other way without an originating
|
||||
// document we can't do a document.open w/o changing the principal of the
|
||||
// document to something like about:blank (as that's the only sane thing to
|
||||
// do when we don't know the origin of this call), and since we can't
|
||||
// change the principals of a document for security reasons we'll have to
|
||||
// refuse to go ahead with this call.
|
||||
|
||||
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 4 -- make sure we're same-origin (not just same origin-domain) with
|
||||
// the entry document.
|
||||
if (!callerDoc->NodePrincipal()->Equals(NodePrincipal())) {
|
||||
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 5 -- if we have an active parser with a nonzero script nesting level,
|
||||
// just no-op.
|
||||
//
|
||||
// The mParserAborted check here is probably wrong. Removing it is
|
||||
// tracked in https://bugzilla.mozilla.org/show_bug.cgi?id=1475000
|
||||
if ((mParser && mParser->HasNonzeroScriptNestingLevel()) || mParserAborted) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Step 6 -- check for open() during unload. Per spec, this is just a check
|
||||
// of the ignore-opens-during-unload counter, but our unload event code
|
||||
// doesn't affect that counter yet (unlike pagehide and beforeunload, which
|
||||
// do), so we check for unload directly.
|
||||
if (ShouldIgnoreOpens()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> shell(mDocumentContainer);
|
||||
if (shell) {
|
||||
bool inUnload;
|
||||
shell->GetIsInUnload(&inUnload);
|
||||
if (inUnload) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
// document.open() inherits the CSP from the opening document.
|
||||
// Please create an actual copy of the CSP (do not share the same
|
||||
// reference) otherwise appending a new policy within the opened
|
||||
// document will be incorrectly propagated to the opening doc.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = callerDoc->GetCsp();
|
||||
if (csp) {
|
||||
RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
|
||||
cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
|
||||
mCSP = cspToInherit;
|
||||
}
|
||||
|
||||
// At this point we know this is a valid-enough document.open() call
|
||||
// and not a no-op. Increment our use counter.
|
||||
SetDocumentAndPageUseCounter(eUseCounter_custom_DocumentOpen);
|
||||
|
||||
// Step 7 -- stop existing navigation of our browsing context (and all other
|
||||
// loads it's doing) if we're the active document of our browsing context.
|
||||
// Note that we do not want to stop anything if there is no existing
|
||||
// navigation.
|
||||
if (shell && IsCurrentActiveDocument() &&
|
||||
shell->GetIsAttemptingToNavigate()) {
|
||||
nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(shell));
|
||||
webnav->Stop(nsIWebNavigation::STOP_NETWORK);
|
||||
|
||||
// The Stop call may have cancelled the onload blocker request or
|
||||
// prevented it from getting added, so we need to make sure it gets added
|
||||
// to the document again otherwise the document could have a non-zero
|
||||
// onload block count without the onload blocker request being in the
|
||||
// loadgroup.
|
||||
EnsureOnloadBlocker();
|
||||
}
|
||||
|
||||
// Step 8 -- clear event listeners out of our DOM tree
|
||||
for (nsINode* node : ShadowIncludingTreeIterator(*this)) {
|
||||
if (EventListenerManager* elm = node->GetExistingListenerManager()) {
|
||||
elm->RemoveAllListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Step 9 -- clear event listeners from our window, if we have one.
|
||||
//
|
||||
// Note that we explicitly want the inner window, and only if we're its
|
||||
// document. We want to do this (per spec) even when we're not the "active
|
||||
// document", so we can't go through GetWindow(), because it might forward to
|
||||
// the wrong inner.
|
||||
if (nsPIDOMWindowInner* win = GetInnerWindow()) {
|
||||
if (win->GetExtantDoc() == this) {
|
||||
if (EventListenerManager* elm =
|
||||
nsGlobalWindowInner::Cast(win)->GetExistingListenerManager()) {
|
||||
elm->RemoveAllListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a parser that has a zero script nesting level, we need to
|
||||
// properly terminate it. We do that after we've removed all the event
|
||||
// listeners (so termination won't trigger event listeners if it does
|
||||
// something to the DOM), but before we remove all elements from the document
|
||||
// (so if termination does modify the DOM in some way we will just blow it
|
||||
// away immediately. See the similar code in WriteCommon that handles the
|
||||
// !IsInsertionPointDefined() case and should stay in sync with this code.
|
||||
if (mParser) {
|
||||
MOZ_ASSERT(!mParser->HasNonzeroScriptNestingLevel(),
|
||||
"Why didn't we take the early return?");
|
||||
// Make sure we don't re-enter.
|
||||
IgnoreOpensDuringUnload ignoreOpenGuard(this);
|
||||
mParser->Terminate();
|
||||
MOZ_RELEASE_ASSERT(!mParser, "mParser should have been null'd out");
|
||||
}
|
||||
|
||||
// Step 10 -- remove all our DOM kids without firing any mutation events.
|
||||
{
|
||||
// We want to ignore any recursive calls to Open() that happen while
|
||||
// disconnecting the node tree. The spec doesn't say to do this, but the
|
||||
// spec also doesn't envision unload events on subframes firing while we do
|
||||
// this, while all browsers fire them in practice. See
|
||||
// <https://github.com/whatwg/html/issues/4611>.
|
||||
IgnoreOpensDuringUnload ignoreOpenGuard(this);
|
||||
DisconnectNodeTree();
|
||||
}
|
||||
|
||||
// Step 11 -- if we're the current document in our docshell, do the
|
||||
// equivalent of pushState() with the new URL we should have.
|
||||
if (shell && IsCurrentActiveDocument()) {
|
||||
nsCOMPtr<nsIURI> newURI = callerDoc->GetDocumentURI();
|
||||
if (callerDoc != this) {
|
||||
nsCOMPtr<nsIURI> noFragmentURI;
|
||||
nsresult rv = NS_GetURIWithoutRef(newURI, getter_AddRefs(noFragmentURI));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
newURI = noFragmentURI.forget();
|
||||
}
|
||||
|
||||
// UpdateURLAndHistory might do various member-setting, so make sure we're
|
||||
// holding strong refs to all the refcounted args on the stack. We can
|
||||
// assume that our caller is holding on to "this" already.
|
||||
nsCOMPtr<nsIURI> currentURI = GetDocumentURI();
|
||||
bool equalURIs;
|
||||
nsresult rv = currentURI->Equals(newURI, &equalURIs);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
nsCOMPtr<nsIStructuredCloneContainer> stateContainer(mStateObjectContainer);
|
||||
rv = shell->UpdateURLAndHistory(this, newURI, stateContainer, EmptyString(),
|
||||
/* aReplace = */ true, currentURI,
|
||||
equalURIs);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// And use the security info of the caller document as well, since
|
||||
// it's the thing providing our data.
|
||||
mSecurityInfo = callerDoc->GetSecurityInfo();
|
||||
|
||||
// This is not mentioned in the spec, but I think that's a spec bug. See
|
||||
// <https://github.com/whatwg/html/issues/4299>. In any case, since our
|
||||
// URL may be changing away from about:blank here, we really want to unset
|
||||
// this flag no matter what, since only about:blank can be an initial
|
||||
// document.
|
||||
SetIsInitialDocument(false);
|
||||
|
||||
// And let our docloader know that it will need to track our load event.
|
||||
nsDocShell::Cast(shell)->SetDocumentOpenedButNotLoaded();
|
||||
}
|
||||
|
||||
// Per spec nothing happens with our URI in other cases, though note
|
||||
// <https://github.com/whatwg/html/issues/4286>.
|
||||
|
||||
// Note that we don't need to do anything here with base URIs per spec.
|
||||
// That said, this might be assuming that we implement
|
||||
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#fallback-base-url
|
||||
// correctly, which we don't right now for the about:blank case.
|
||||
|
||||
// Step 12, but note <https://github.com/whatwg/html/issues/4292>.
|
||||
mSkipLoadEventAfterClose = mLoadEventFiring;
|
||||
|
||||
// Preliminary to steps 13-16. Set our ready state to uninitialized before
|
||||
// we do anything else, so we can then proceed to later ready state levels.
|
||||
SetReadyStateInternal(READYSTATE_UNINITIALIZED,
|
||||
/* updateTimingInformation = */ false);
|
||||
|
||||
// Step 13 -- set our compat mode to standards.
|
||||
SetCompatibilityMode(eCompatibility_FullStandards);
|
||||
|
||||
// Step 14 -- create a new parser associated with document. This also does
|
||||
// step 16 implicitly.
|
||||
mParserAborted = false;
|
||||
RefPtr<nsHtml5Parser> parser = nsHtml5Module::NewHtml5Parser();
|
||||
mParser = parser;
|
||||
parser->Initialize(this, GetDocumentURI(), shell, nullptr);
|
||||
if (mReferrerPolicySet) {
|
||||
// CSP may have set the referrer policy, so a speculative parser should
|
||||
// start with the new referrer policy.
|
||||
nsHtml5TreeOpExecutor* executor = nullptr;
|
||||
executor = static_cast<nsHtml5TreeOpExecutor*>(mParser->GetContentSink());
|
||||
if (executor && mReferrerPolicySet) {
|
||||
executor->SetSpeculationReferrerPolicy(
|
||||
static_cast<net::ReferrerPolicy>(mReferrerPolicy));
|
||||
}
|
||||
}
|
||||
nsresult rv = parser->StartExecutor();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (shell) {
|
||||
// Prepare the docshell and the document viewer for the impending
|
||||
// out-of-band document.write()
|
||||
shell->PrepareForNewContentModel();
|
||||
|
||||
nsCOMPtr<nsIContentViewer> cv;
|
||||
shell->GetContentViewer(getter_AddRefs(cv));
|
||||
if (cv) {
|
||||
cv->LoadStart(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 15.
|
||||
SetReadyStateInternal(Document::READYSTATE_LOADING,
|
||||
/* updateTimingInformation = */ false);
|
||||
|
||||
// Step 16 happened with step 14 above.
|
||||
|
||||
// Step 17.
|
||||
return this;
|
||||
}
|
||||
|
||||
void Document::Close(ErrorResult& rv) {
|
||||
if (!IsHTMLDocument()) {
|
||||
// No calling document.close() on XHTML!
|
||||
|
||||
rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ShouldThrowOnDynamicMarkupInsertion()) {
|
||||
rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mParser || !mParser->IsScriptCreated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
++mWriteLevel;
|
||||
rv = (static_cast<nsHtml5Parser*>(mParser.get()))
|
||||
->Parse(EmptyString(), nullptr, true);
|
||||
--mWriteLevel;
|
||||
|
||||
// Even if that Parse() call failed, do the rest of this method
|
||||
|
||||
// XXX Make sure that all the document.written content is
|
||||
// reflowed. We should remove this call once we change
|
||||
// Document::OpenCommon() so that it completely destroys the
|
||||
// earlier document's content and frame hierarchy. Right now, it
|
||||
// re-uses the earlier document's root content object and
|
||||
// corresponding frame objects. These re-used frame objects think
|
||||
// that they have already been reflowed, so they drop initial
|
||||
// reflows. For certain cases of document.written content, like a
|
||||
// frameset document, the dropping of the initial reflow means
|
||||
// that we end up in document.close() without appended any reflow
|
||||
// commands to the reflow queue and, consequently, without adding
|
||||
// the dummy layout request to the load group. Since the dummy
|
||||
// layout request is not added to the load group, the onload
|
||||
// handler of the frameset fires before the frames get reflowed
|
||||
// and loaded. That is the long explanation for why we need this
|
||||
// one line of code here!
|
||||
// XXXbz as far as I can tell this may not be needed anymore; all
|
||||
// the testcases in bug 57636 pass without this line... Leaving
|
||||
// it be for now, though. In any case, there's no reason to do
|
||||
// this if we have no presshell, since in that case none of the
|
||||
// above about reusing frames applies.
|
||||
//
|
||||
// XXXhsivonen keeping this around for bug 577508 / 253951 still :-(
|
||||
if (GetPresShell()) {
|
||||
FlushPendingNotifications(FlushType::Layout);
|
||||
}
|
||||
}
|
||||
|
||||
void Document::WriteCommon(const Sequence<nsString>& aText,
|
||||
bool aNewlineTerminate, mozilla::ErrorResult& rv) {
|
||||
// Fast path the common case
|
||||
if (aText.Length() == 1) {
|
||||
WriteCommon(aText[0], aNewlineTerminate, rv);
|
||||
} else {
|
||||
// XXXbz it would be nice if we could pass all the strings to the parser
|
||||
// without having to do all this copying and then ask it to start
|
||||
// parsing....
|
||||
nsString text;
|
||||
for (uint32_t i = 0; i < aText.Length(); ++i) {
|
||||
text.Append(aText[i]);
|
||||
}
|
||||
WriteCommon(text, aNewlineTerminate, rv);
|
||||
}
|
||||
}
|
||||
|
||||
void Document::WriteCommon(const nsAString& aText, bool aNewlineTerminate,
|
||||
ErrorResult& aRv) {
|
||||
mTooDeepWriteRecursion =
|
||||
(mWriteLevel > NS_MAX_DOCUMENT_WRITE_DEPTH || mTooDeepWriteRecursion);
|
||||
if (NS_WARN_IF(mTooDeepWriteRecursion)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsHTMLDocument() || mDisableDocWrite) {
|
||||
// No calling document.write*() on XHTML!
|
||||
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ShouldThrowOnDynamicMarkupInsertion()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mParserAborted) {
|
||||
// Hixie says aborting the parser doesn't undefine the insertion point.
|
||||
// However, since we null out mParser in that case, we track the
|
||||
// theoretically defined insertion point using mParserAborted.
|
||||
return;
|
||||
}
|
||||
|
||||
// Implement Step 4.1 of:
|
||||
// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-write-steps
|
||||
if (ShouldIgnoreOpens()) {
|
||||
return;
|
||||
}
|
||||
|
||||
void* key = GenerateParserKey();
|
||||
if (mParser && !mParser->IsInsertionPointDefined()) {
|
||||
if (mIgnoreDestructiveWritesCounter) {
|
||||
// Instead of implying a call to document.open(), ignore the call.
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM Events"), this,
|
||||
nsContentUtils::eDOM_PROPERTIES, "DocumentWriteIgnored", nullptr, 0,
|
||||
mDocumentURI);
|
||||
return;
|
||||
}
|
||||
// The spec doesn't tell us to ignore opens from here, but we need to
|
||||
// ensure opens are ignored here. See similar code in Open() that handles
|
||||
// the case of an existing parser which is not currently running script and
|
||||
// should stay in sync with this code.
|
||||
IgnoreOpensDuringUnload ignoreOpenGuard(this);
|
||||
mParser->Terminate();
|
||||
MOZ_RELEASE_ASSERT(!mParser, "mParser should have been null'd out");
|
||||
}
|
||||
|
||||
if (!mParser) {
|
||||
if (mIgnoreDestructiveWritesCounter) {
|
||||
// Instead of implying a call to document.open(), ignore the call.
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM Events"), this,
|
||||
nsContentUtils::eDOM_PROPERTIES, "DocumentWriteIgnored", nullptr, 0,
|
||||
mDocumentURI);
|
||||
return;
|
||||
}
|
||||
|
||||
Open(Optional<nsAString>(), EmptyString(), aRv);
|
||||
|
||||
// If Open() fails, or if it didn't create a parser (as it won't
|
||||
// if the user chose to not discard the current document through
|
||||
// onbeforeunload), don't write anything.
|
||||
if (aRv.Failed() || !mParser) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static NS_NAMED_LITERAL_STRING(new_line, "\n");
|
||||
|
||||
++mWriteLevel;
|
||||
|
||||
// This could be done with less code, but for performance reasons it
|
||||
// makes sense to have the code for two separate Parse() calls here
|
||||
// since the concatenation of strings costs more than we like. And
|
||||
// why pay that price when we don't need to?
|
||||
if (aNewlineTerminate) {
|
||||
aRv = (static_cast<nsHtml5Parser*>(mParser.get()))
|
||||
->Parse(aText + new_line, key, false);
|
||||
} else {
|
||||
aRv =
|
||||
(static_cast<nsHtml5Parser*>(mParser.get()))->Parse(aText, key, false);
|
||||
}
|
||||
|
||||
--mWriteLevel;
|
||||
|
||||
mTooDeepWriteRecursion = (mWriteLevel != 0 && mTooDeepWriteRecursion);
|
||||
}
|
||||
|
||||
void Document::Write(const Sequence<nsString>& aText, ErrorResult& rv) {
|
||||
WriteCommon(aText, false, rv);
|
||||
}
|
||||
|
||||
void Document::Writeln(const Sequence<nsString>& aText, ErrorResult& rv) {
|
||||
WriteCommon(aText, true, rv);
|
||||
}
|
||||
|
||||
void* Document::GenerateParserKey(void) {
|
||||
if (!mScriptLoader) {
|
||||
// If we don't have a script loader, then the parser probably isn't parsing
|
||||
// anything anyway, so just return null.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The script loader provides us with the currently executing script element,
|
||||
// which is guaranteed to be unique per script.
|
||||
nsIScriptElement* script = mScriptLoader->GetCurrentParserInsertedScript();
|
||||
if (script && mParser && mParser->IsScriptCreated()) {
|
||||
nsCOMPtr<nsIParser> creatorParser = script->GetCreatorParser();
|
||||
if (creatorParser != mParser) {
|
||||
// Make scripts that aren't inserted by the active parser of this document
|
||||
// participate in the context of the script that document.open()ed
|
||||
// this document.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool Document::MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
|
||||
nsAtom* aAtom, void* aData) {
|
||||
|
|
|
@ -1280,6 +1280,22 @@ class Document : public nsINode,
|
|||
*/
|
||||
void DisableCookieAccess() { mDisableCookieAccess = true; }
|
||||
|
||||
/**
|
||||
* Set compatibility mode for this document
|
||||
*/
|
||||
void SetCompatibilityMode(nsCompatibility aMode);
|
||||
|
||||
/**
|
||||
* Called to disable client access to document.write() API from user
|
||||
* JavaScript code.
|
||||
*/
|
||||
void SetDocWriteDisabled(bool aDisabled) { mDisableDocWrite = aDisabled; }
|
||||
|
||||
/**
|
||||
* Whether a document.write() call is in progress.
|
||||
*/
|
||||
bool IsWriting() const { return mWriteLevel != uint32_t(0); }
|
||||
|
||||
/**
|
||||
* Access HTTP header data (this may also get set from other
|
||||
* sources, like HTML META tags).
|
||||
|
@ -3289,6 +3305,16 @@ class Document : public nsINode,
|
|||
return GetFuncStringContentList<nsCachableElementsByNameNodeList>(
|
||||
this, MatchNameAttribute, nullptr, UseExistingNameString, aName);
|
||||
}
|
||||
Document* Open(const mozilla::dom::Optional<nsAString>& /* unused */,
|
||||
const nsAString& /* unused */, mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> Open(
|
||||
const nsAString& aURL, const nsAString& aName, const nsAString& aFeatures,
|
||||
bool aReplace, mozilla::ErrorResult& rv);
|
||||
void Close(mozilla::ErrorResult& rv);
|
||||
void Write(const mozilla::dom::Sequence<nsString>& aText,
|
||||
mozilla::ErrorResult& rv);
|
||||
void Writeln(const mozilla::dom::Sequence<nsString>& aText,
|
||||
mozilla::ErrorResult& rv);
|
||||
Nullable<WindowProxyHolder> GetDefaultView() const;
|
||||
Element* GetActiveElement();
|
||||
bool HasFocus(ErrorResult& rv) const;
|
||||
|
@ -3916,6 +3942,14 @@ class Document : public nsINode,
|
|||
already_AddRefed<nsIURI> RegistrableDomainSuffixOfInternal(
|
||||
const nsAString& aHostSuffixString, nsIURI* aOrigHost);
|
||||
|
||||
void WriteCommon(const nsAString& aText, bool aNewlineTerminate,
|
||||
mozilla::ErrorResult& aRv);
|
||||
// A version of WriteCommon used by WebIDL bindings
|
||||
void WriteCommon(const mozilla::dom::Sequence<nsString>& aText,
|
||||
bool aNewlineTerminate, mozilla::ErrorResult& rv);
|
||||
|
||||
void* GenerateParserKey(void);
|
||||
|
||||
private:
|
||||
void RecordContentBlockingLog(
|
||||
const nsACString& aOrigin, uint32_t aType, bool aBlocked,
|
||||
|
@ -4388,6 +4422,13 @@ class Document : public nsINode,
|
|||
// When false, the .cookies property is completely disabled
|
||||
bool mDisableCookieAccess : 1;
|
||||
|
||||
// When false, the document.write() API is disabled.
|
||||
bool mDisableDocWrite : 1;
|
||||
|
||||
// Has document.write() been called with a recursion depth higher than
|
||||
// allowed?
|
||||
bool mTooDeepWriteRecursion : 1;
|
||||
|
||||
uint8_t mPendingFullscreenRequests;
|
||||
|
||||
uint8_t mXMLDeclarationBits;
|
||||
|
@ -4398,6 +4439,12 @@ class Document : public nsINode,
|
|||
// Onload blockers which haven't been activated yet.
|
||||
uint32_t mAsyncOnloadBlockCount;
|
||||
|
||||
// Tracks if we are currently processing any document.write calls (either
|
||||
// implicit or explicit). Note that if a write call writes out something which
|
||||
// would block the parser, then mWriteLevel will be incorrect until the parser
|
||||
// finishes processing that script.
|
||||
uint32_t mWriteLevel;
|
||||
|
||||
// Compatibility mode
|
||||
nsCompatibility mCompatMode;
|
||||
|
||||
|
|
|
@ -660,20 +660,18 @@ NS_IMETHODIMP
|
|||
HTMLContentSink::WillBuildModel(nsDTDMode aDTDMode) {
|
||||
WillBuildModelImpl();
|
||||
|
||||
if (mHTMLDocument) {
|
||||
nsCompatibility mode = eCompatibility_NavQuirks;
|
||||
switch (aDTDMode) {
|
||||
case eDTDMode_full_standards:
|
||||
mode = eCompatibility_FullStandards;
|
||||
break;
|
||||
case eDTDMode_almost_standards:
|
||||
mode = eCompatibility_AlmostStandards;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mHTMLDocument->SetCompatibilityMode(mode);
|
||||
nsCompatibility mode = eCompatibility_NavQuirks;
|
||||
switch (aDTDMode) {
|
||||
case eDTDMode_full_standards:
|
||||
mode = eCompatibility_FullStandards;
|
||||
break;
|
||||
case eDTDMode_almost_standards:
|
||||
mode = eCompatibility_AlmostStandards;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mDocument->SetCompatibilityMode(mode);
|
||||
|
||||
// Notify document that the load is beginning
|
||||
mDocument->BeginLoad();
|
||||
|
|
|
@ -120,8 +120,6 @@
|
|||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
#define NS_MAX_DOCUMENT_WRITE_DEPTH 20
|
||||
|
||||
#include "prtime.h"
|
||||
|
||||
//#define DEBUG_charset
|
||||
|
@ -171,10 +169,7 @@ nsHTMLDocument::nsHTMLDocument()
|
|||
: Document("text/html"),
|
||||
mContentListHolder(nullptr),
|
||||
mNumForms(0),
|
||||
mWriteLevel(0),
|
||||
mLoadFlags(0),
|
||||
mTooDeepWriteRecursion(false),
|
||||
mDisableDocWrite(false),
|
||||
mWarnedWidthHeight(false),
|
||||
mContentEditableCount(0),
|
||||
mEditingState(EditingState::eOff),
|
||||
|
@ -751,17 +746,6 @@ void nsHTMLDocument::EndLoad() {
|
|||
}
|
||||
}
|
||||
|
||||
void nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode) {
|
||||
NS_ASSERTION(IsHTMLDocument() || aMode == eCompatibility_FullStandards,
|
||||
"Bad compat mode for XHTML document!");
|
||||
|
||||
if (mCompatMode == aMode) {
|
||||
return;
|
||||
}
|
||||
mCompatMode = aMode;
|
||||
CompatibilityModeChanged();
|
||||
}
|
||||
|
||||
bool nsHTMLDocument::UseWidthDeviceWidthFallbackViewport() const {
|
||||
if (mIsPlainText) {
|
||||
// Plain text documents are simple enough that font inflation doesn't offer
|
||||
|
@ -801,465 +785,6 @@ bool nsHTMLDocument::IsRegistrableDomainSuffixOfOrEqualTo(
|
|||
return true;
|
||||
}
|
||||
|
||||
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> nsHTMLDocument::Open(
|
||||
const nsAString& aURL, const nsAString& aName, const nsAString& aFeatures,
|
||||
bool aReplace, ErrorResult& rv) {
|
||||
MOZ_ASSERT(nsContentUtils::CanCallerAccess(this),
|
||||
"XOW should have caught this!");
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = GetInnerWindow();
|
||||
if (!window) {
|
||||
rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindowOuter> outer =
|
||||
nsPIDOMWindowOuter::GetFromCurrentInner(window);
|
||||
if (!outer) {
|
||||
rv.Throw(NS_ERROR_NOT_INITIALIZED);
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<nsGlobalWindowOuter> win = nsGlobalWindowOuter::Cast(outer);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> newWindow;
|
||||
// XXXbz We ignore aReplace for now.
|
||||
rv = win->OpenJS(aURL, aName, aFeatures, getter_AddRefs(newWindow));
|
||||
if (!newWindow) {
|
||||
return nullptr;
|
||||
}
|
||||
return WindowProxyHolder(newWindow->GetBrowsingContext());
|
||||
}
|
||||
|
||||
Document* nsHTMLDocument::Open(const Optional<nsAString>& /* unused */,
|
||||
const nsAString& /* unused */,
|
||||
ErrorResult& aError) {
|
||||
// Implements
|
||||
// <https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-open-steps>
|
||||
|
||||
MOZ_ASSERT(nsContentUtils::CanCallerAccess(this),
|
||||
"XOW should have caught this!");
|
||||
|
||||
// Step 1 -- throw if we're an XML document.
|
||||
if (!IsHTMLDocument() || mDisableDocWrite) {
|
||||
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 2 -- throw if dynamic markup insertion should throw.
|
||||
if (ShouldThrowOnDynamicMarkupInsertion()) {
|
||||
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 3 -- get the entry document, so we can use it for security checks.
|
||||
nsCOMPtr<Document> callerDoc = GetEntryDocument();
|
||||
if (!callerDoc) {
|
||||
// If we're called from C++ or in some other way without an originating
|
||||
// document we can't do a document.open w/o changing the principal of the
|
||||
// document to something like about:blank (as that's the only sane thing to
|
||||
// do when we don't know the origin of this call), and since we can't
|
||||
// change the principals of a document for security reasons we'll have to
|
||||
// refuse to go ahead with this call.
|
||||
|
||||
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 4 -- make sure we're same-origin (not just same origin-domain) with
|
||||
// the entry document.
|
||||
if (!callerDoc->NodePrincipal()->Equals(NodePrincipal())) {
|
||||
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 5 -- if we have an active parser with a nonzero script nesting level,
|
||||
// just no-op.
|
||||
//
|
||||
// The mParserAborted check here is probably wrong. Removing it is
|
||||
// tracked in https://bugzilla.mozilla.org/show_bug.cgi?id=1475000
|
||||
if ((mParser && mParser->HasNonzeroScriptNestingLevel()) || mParserAborted) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Step 6 -- check for open() during unload. Per spec, this is just a check
|
||||
// of the ignore-opens-during-unload counter, but our unload event code
|
||||
// doesn't affect that counter yet (unlike pagehide and beforeunload, which
|
||||
// do), so we check for unload directly.
|
||||
if (ShouldIgnoreOpens()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> shell(mDocumentContainer);
|
||||
if (shell) {
|
||||
bool inUnload;
|
||||
shell->GetIsInUnload(&inUnload);
|
||||
if (inUnload) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
// document.open() inherits the CSP from the opening document.
|
||||
// Please create an actual copy of the CSP (do not share the same
|
||||
// reference) otherwise appending a new policy within the opened
|
||||
// document will be incorrectly propagated to the opening doc.
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp = callerDoc->GetCsp();
|
||||
if (csp) {
|
||||
RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
|
||||
cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
|
||||
mCSP = cspToInherit;
|
||||
}
|
||||
|
||||
// At this point we know this is a valid-enough document.open() call
|
||||
// and not a no-op. Increment our use counter.
|
||||
SetDocumentAndPageUseCounter(eUseCounter_custom_DocumentOpen);
|
||||
|
||||
// Step 7 -- stop existing navigation of our browsing context (and all other
|
||||
// loads it's doing) if we're the active document of our browsing context.
|
||||
// Note that we do not want to stop anything if there is no existing
|
||||
// navigation.
|
||||
if (shell && IsCurrentActiveDocument() &&
|
||||
shell->GetIsAttemptingToNavigate()) {
|
||||
nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(shell));
|
||||
webnav->Stop(nsIWebNavigation::STOP_NETWORK);
|
||||
|
||||
// The Stop call may have cancelled the onload blocker request or
|
||||
// prevented it from getting added, so we need to make sure it gets added
|
||||
// to the document again otherwise the document could have a non-zero
|
||||
// onload block count without the onload blocker request being in the
|
||||
// loadgroup.
|
||||
EnsureOnloadBlocker();
|
||||
}
|
||||
|
||||
// Step 8 -- clear event listeners out of our DOM tree
|
||||
for (nsINode* node : ShadowIncludingTreeIterator(*this)) {
|
||||
if (EventListenerManager* elm = node->GetExistingListenerManager()) {
|
||||
elm->RemoveAllListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Step 9 -- clear event listeners from our window, if we have one.
|
||||
//
|
||||
// Note that we explicitly want the inner window, and only if we're its
|
||||
// document. We want to do this (per spec) even when we're not the "active
|
||||
// document", so we can't go through GetWindow(), because it might forward to
|
||||
// the wrong inner.
|
||||
if (nsPIDOMWindowInner* win = GetInnerWindow()) {
|
||||
if (win->GetExtantDoc() == this) {
|
||||
if (EventListenerManager* elm =
|
||||
nsGlobalWindowInner::Cast(win)->GetExistingListenerManager()) {
|
||||
elm->RemoveAllListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a parser that has a zero script nesting level, we need to
|
||||
// properly terminate it. We do that after we've removed all the event
|
||||
// listeners (so termination won't trigger event listeners if it does
|
||||
// something to the DOM), but before we remove all elements from the document
|
||||
// (so if termination does modify the DOM in some way we will just blow it
|
||||
// away immediately. See the similar code in WriteCommon that handles the
|
||||
// !IsInsertionPointDefined() case and should stay in sync with this code.
|
||||
if (mParser) {
|
||||
MOZ_ASSERT(!mParser->HasNonzeroScriptNestingLevel(),
|
||||
"Why didn't we take the early return?");
|
||||
// Make sure we don't re-enter.
|
||||
IgnoreOpensDuringUnload ignoreOpenGuard(this);
|
||||
mParser->Terminate();
|
||||
MOZ_RELEASE_ASSERT(!mParser, "mParser should have been null'd out");
|
||||
}
|
||||
|
||||
// Step 10 -- remove all our DOM kids without firing any mutation events.
|
||||
{
|
||||
// We want to ignore any recursive calls to Open() that happen while
|
||||
// disconnecting the node tree. The spec doesn't say to do this, but the
|
||||
// spec also doesn't envision unload events on subframes firing while we do
|
||||
// this, while all browsers fire them in practice. See
|
||||
// <https://github.com/whatwg/html/issues/4611>.
|
||||
IgnoreOpensDuringUnload ignoreOpenGuard(this);
|
||||
DisconnectNodeTree();
|
||||
}
|
||||
|
||||
// Step 11 -- if we're the current document in our docshell, do the
|
||||
// equivalent of pushState() with the new URL we should have.
|
||||
if (shell && IsCurrentActiveDocument()) {
|
||||
nsCOMPtr<nsIURI> newURI = callerDoc->GetDocumentURI();
|
||||
if (callerDoc != this) {
|
||||
nsCOMPtr<nsIURI> noFragmentURI;
|
||||
nsresult rv = NS_GetURIWithoutRef(newURI, getter_AddRefs(noFragmentURI));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
newURI = noFragmentURI.forget();
|
||||
}
|
||||
|
||||
// UpdateURLAndHistory might do various member-setting, so make sure we're
|
||||
// holding strong refs to all the refcounted args on the stack. We can
|
||||
// assume that our caller is holding on to "this" already.
|
||||
nsCOMPtr<nsIURI> currentURI = GetDocumentURI();
|
||||
bool equalURIs;
|
||||
nsresult rv = currentURI->Equals(newURI, &equalURIs);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
nsCOMPtr<nsIStructuredCloneContainer> stateContainer(mStateObjectContainer);
|
||||
rv = shell->UpdateURLAndHistory(this, newURI, stateContainer, EmptyString(),
|
||||
/* aReplace = */ true, currentURI,
|
||||
equalURIs);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// And use the security info of the caller document as well, since
|
||||
// it's the thing providing our data.
|
||||
mSecurityInfo = callerDoc->GetSecurityInfo();
|
||||
|
||||
// This is not mentioned in the spec, but I think that's a spec bug. See
|
||||
// <https://github.com/whatwg/html/issues/4299>. In any case, since our
|
||||
// URL may be changing away from about:blank here, we really want to unset
|
||||
// this flag no matter what, since only about:blank can be an initial
|
||||
// document.
|
||||
SetIsInitialDocument(false);
|
||||
|
||||
// And let our docloader know that it will need to track our load event.
|
||||
nsDocShell::Cast(shell)->SetDocumentOpenedButNotLoaded();
|
||||
}
|
||||
|
||||
// Per spec nothing happens with our URI in other cases, though note
|
||||
// <https://github.com/whatwg/html/issues/4286>.
|
||||
|
||||
// Note that we don't need to do anything here with base URIs per spec.
|
||||
// That said, this might be assuming that we implement
|
||||
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#fallback-base-url
|
||||
// correctly, which we don't right now for the about:blank case.
|
||||
|
||||
// Step 12, but note <https://github.com/whatwg/html/issues/4292>.
|
||||
mSkipLoadEventAfterClose = mLoadEventFiring;
|
||||
|
||||
// Preliminary to steps 13-16. Set our ready state to uninitialized before
|
||||
// we do anything else, so we can then proceed to later ready state levels.
|
||||
SetReadyStateInternal(READYSTATE_UNINITIALIZED,
|
||||
/* updateTimingInformation = */ false);
|
||||
|
||||
// Step 13 -- set our compat mode to standards.
|
||||
SetCompatibilityMode(eCompatibility_FullStandards);
|
||||
|
||||
// Step 14 -- create a new parser associated with document. This also does
|
||||
// step 16 implicitly.
|
||||
mParserAborted = false;
|
||||
RefPtr<nsHtml5Parser> parser = nsHtml5Module::NewHtml5Parser();
|
||||
mParser = parser;
|
||||
parser->Initialize(this, GetDocumentURI(), shell, nullptr);
|
||||
if (mReferrerPolicySet) {
|
||||
// CSP may have set the referrer policy, so a speculative parser should
|
||||
// start with the new referrer policy.
|
||||
nsHtml5TreeOpExecutor* executor = nullptr;
|
||||
executor = static_cast<nsHtml5TreeOpExecutor*>(mParser->GetContentSink());
|
||||
if (executor && mReferrerPolicySet) {
|
||||
executor->SetSpeculationReferrerPolicy(
|
||||
static_cast<ReferrerPolicy>(mReferrerPolicy));
|
||||
}
|
||||
}
|
||||
nsresult rv = parser->StartExecutor();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aError.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (shell) {
|
||||
// Prepare the docshell and the document viewer for the impending
|
||||
// out-of-band document.write()
|
||||
shell->PrepareForNewContentModel();
|
||||
|
||||
nsCOMPtr<nsIContentViewer> cv;
|
||||
shell->GetContentViewer(getter_AddRefs(cv));
|
||||
if (cv) {
|
||||
cv->LoadStart(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 15.
|
||||
SetReadyStateInternal(Document::READYSTATE_LOADING,
|
||||
/* updateTimingInformation = */ false);
|
||||
|
||||
// Step 16 happened with step 14 above.
|
||||
|
||||
// Step 17.
|
||||
return this;
|
||||
}
|
||||
|
||||
void nsHTMLDocument::Close(ErrorResult& rv) {
|
||||
if (!IsHTMLDocument()) {
|
||||
// No calling document.close() on XHTML!
|
||||
|
||||
rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ShouldThrowOnDynamicMarkupInsertion()) {
|
||||
rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mParser || !mParser->IsScriptCreated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
++mWriteLevel;
|
||||
rv = (static_cast<nsHtml5Parser*>(mParser.get()))
|
||||
->Parse(EmptyString(), nullptr, true);
|
||||
--mWriteLevel;
|
||||
|
||||
// Even if that Parse() call failed, do the rest of this method
|
||||
|
||||
// XXX Make sure that all the document.written content is
|
||||
// reflowed. We should remove this call once we change
|
||||
// nsHTMLDocument::OpenCommon() so that it completely destroys the
|
||||
// earlier document's content and frame hierarchy. Right now, it
|
||||
// re-uses the earlier document's root content object and
|
||||
// corresponding frame objects. These re-used frame objects think
|
||||
// that they have already been reflowed, so they drop initial
|
||||
// reflows. For certain cases of document.written content, like a
|
||||
// frameset document, the dropping of the initial reflow means
|
||||
// that we end up in document.close() without appended any reflow
|
||||
// commands to the reflow queue and, consequently, without adding
|
||||
// the dummy layout request to the load group. Since the dummy
|
||||
// layout request is not added to the load group, the onload
|
||||
// handler of the frameset fires before the frames get reflowed
|
||||
// and loaded. That is the long explanation for why we need this
|
||||
// one line of code here!
|
||||
// XXXbz as far as I can tell this may not be needed anymore; all
|
||||
// the testcases in bug 57636 pass without this line... Leaving
|
||||
// it be for now, though. In any case, there's no reason to do
|
||||
// this if we have no presshell, since in that case none of the
|
||||
// above about reusing frames applies.
|
||||
//
|
||||
// XXXhsivonen keeping this around for bug 577508 / 253951 still :-(
|
||||
if (GetPresShell()) {
|
||||
FlushPendingNotifications(FlushType::Layout);
|
||||
}
|
||||
}
|
||||
|
||||
void nsHTMLDocument::WriteCommon(const Sequence<nsString>& aText,
|
||||
bool aNewlineTerminate,
|
||||
mozilla::ErrorResult& rv) {
|
||||
// Fast path the common case
|
||||
if (aText.Length() == 1) {
|
||||
WriteCommon(aText[0], aNewlineTerminate, rv);
|
||||
} else {
|
||||
// XXXbz it would be nice if we could pass all the strings to the parser
|
||||
// without having to do all this copying and then ask it to start
|
||||
// parsing....
|
||||
nsString text;
|
||||
for (uint32_t i = 0; i < aText.Length(); ++i) {
|
||||
text.Append(aText[i]);
|
||||
}
|
||||
WriteCommon(text, aNewlineTerminate, rv);
|
||||
}
|
||||
}
|
||||
|
||||
void nsHTMLDocument::WriteCommon(const nsAString& aText, bool aNewlineTerminate,
|
||||
ErrorResult& aRv) {
|
||||
mTooDeepWriteRecursion =
|
||||
(mWriteLevel > NS_MAX_DOCUMENT_WRITE_DEPTH || mTooDeepWriteRecursion);
|
||||
if (NS_WARN_IF(mTooDeepWriteRecursion)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsHTMLDocument() || mDisableDocWrite) {
|
||||
// No calling document.write*() on XHTML!
|
||||
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ShouldThrowOnDynamicMarkupInsertion()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mParserAborted) {
|
||||
// Hixie says aborting the parser doesn't undefine the insertion point.
|
||||
// However, since we null out mParser in that case, we track the
|
||||
// theoretically defined insertion point using mParserAborted.
|
||||
return;
|
||||
}
|
||||
|
||||
// Implement Step 4.1 of:
|
||||
// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-write-steps
|
||||
if (ShouldIgnoreOpens()) {
|
||||
return;
|
||||
}
|
||||
|
||||
void* key = GenerateParserKey();
|
||||
if (mParser && !mParser->IsInsertionPointDefined()) {
|
||||
if (mIgnoreDestructiveWritesCounter) {
|
||||
// Instead of implying a call to document.open(), ignore the call.
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM Events"), this,
|
||||
nsContentUtils::eDOM_PROPERTIES, "DocumentWriteIgnored", nullptr, 0,
|
||||
mDocumentURI);
|
||||
return;
|
||||
}
|
||||
// The spec doesn't tell us to ignore opens from here, but we need to
|
||||
// ensure opens are ignored here. See similar code in Open() that handles
|
||||
// the case of an existing parser which is not currently running script and
|
||||
// should stay in sync with this code.
|
||||
IgnoreOpensDuringUnload ignoreOpenGuard(this);
|
||||
mParser->Terminate();
|
||||
MOZ_RELEASE_ASSERT(!mParser, "mParser should have been null'd out");
|
||||
}
|
||||
|
||||
if (!mParser) {
|
||||
if (mIgnoreDestructiveWritesCounter) {
|
||||
// Instead of implying a call to document.open(), ignore the call.
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM Events"), this,
|
||||
nsContentUtils::eDOM_PROPERTIES, "DocumentWriteIgnored", nullptr, 0,
|
||||
mDocumentURI);
|
||||
return;
|
||||
}
|
||||
|
||||
Open(Optional<nsAString>(), EmptyString(), aRv);
|
||||
|
||||
// If Open() fails, or if it didn't create a parser (as it won't
|
||||
// if the user chose to not discard the current document through
|
||||
// onbeforeunload), don't write anything.
|
||||
if (aRv.Failed() || !mParser) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static NS_NAMED_LITERAL_STRING(new_line, "\n");
|
||||
|
||||
++mWriteLevel;
|
||||
|
||||
// This could be done with less code, but for performance reasons it
|
||||
// makes sense to have the code for two separate Parse() calls here
|
||||
// since the concatenation of strings costs more than we like. And
|
||||
// why pay that price when we don't need to?
|
||||
if (aNewlineTerminate) {
|
||||
aRv = (static_cast<nsHtml5Parser*>(mParser.get()))
|
||||
->Parse(aText + new_line, key, false);
|
||||
} else {
|
||||
aRv =
|
||||
(static_cast<nsHtml5Parser*>(mParser.get()))->Parse(aText, key, false);
|
||||
}
|
||||
|
||||
--mWriteLevel;
|
||||
|
||||
mTooDeepWriteRecursion = (mWriteLevel != 0 && mTooDeepWriteRecursion);
|
||||
}
|
||||
|
||||
void nsHTMLDocument::Write(const Sequence<nsString>& aText, ErrorResult& rv) {
|
||||
WriteCommon(aText, false, rv);
|
||||
}
|
||||
|
||||
void nsHTMLDocument::Writeln(const Sequence<nsString>& aText, ErrorResult& rv) {
|
||||
WriteCommon(aText, true, rv);
|
||||
}
|
||||
|
||||
void nsHTMLDocument::AddedForm() { ++mNumForms; }
|
||||
|
||||
void nsHTMLDocument::RemovedForm() { --mNumForms; }
|
||||
|
@ -1417,28 +942,6 @@ bool nsHTMLDocument::MatchFormControls(Element* aElement, int32_t aNamespaceID,
|
|||
return aElement->IsNodeOfType(nsIContent::eHTML_FORM_CONTROL);
|
||||
}
|
||||
|
||||
void* nsHTMLDocument::GenerateParserKey(void) {
|
||||
if (!mScriptLoader) {
|
||||
// If we don't have a script loader, then the parser probably isn't parsing
|
||||
// anything anyway, so just return null.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The script loader provides us with the currently executing script element,
|
||||
// which is guaranteed to be unique per script.
|
||||
nsIScriptElement* script = mScriptLoader->GetCurrentParserInsertedScript();
|
||||
if (script && mParser && mParser->IsScriptCreated()) {
|
||||
nsCOMPtr<nsIParser> creatorParser = script->GetCreatorParser();
|
||||
if (creatorParser != mParser) {
|
||||
// Make scripts that aren't inserted by the active parser of this document
|
||||
// participate in the context of the script that document.open()ed
|
||||
// this document.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
void nsHTMLDocument::GetDesignMode(nsAString& aDesignMode) {
|
||||
if (HasFlag(NODE_IS_EDITABLE)) {
|
||||
aDesignMode.AssignLiteral("on");
|
||||
|
|
|
@ -74,10 +74,6 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
|||
|
||||
public:
|
||||
// nsIHTMLDocument
|
||||
virtual void SetCompatibilityMode(nsCompatibility aMode) override;
|
||||
|
||||
virtual bool IsWriting() override { return mWriteLevel != uint32_t(0); }
|
||||
|
||||
virtual Element* GetUnfocusedKeyEventTarget() override;
|
||||
|
||||
nsContentList* GetExistingForms() const { return mForms; }
|
||||
|
@ -96,9 +92,6 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
|||
virtual void SetIsXHTML(bool aXHTML) override {
|
||||
mType = (aXHTML ? eXHTML : eHTML);
|
||||
}
|
||||
virtual void SetDocWriteDisabled(bool aDisabled) override {
|
||||
mDisableDocWrite = aDisabled;
|
||||
}
|
||||
|
||||
nsresult ChangeContentEditableCount(nsIContent* aElement,
|
||||
int32_t aChange) override;
|
||||
|
@ -152,16 +145,6 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
|||
}
|
||||
}
|
||||
void GetSupportedNames(nsTArray<nsString>& aNames);
|
||||
Document* Open(const mozilla::dom::Optional<nsAString>& /* unused */,
|
||||
const nsAString& /* unused */, mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> Open(
|
||||
const nsAString& aURL, const nsAString& aName, const nsAString& aFeatures,
|
||||
bool aReplace, mozilla::ErrorResult& rv);
|
||||
void Close(mozilla::ErrorResult& rv);
|
||||
void Write(const mozilla::dom::Sequence<nsString>& aText,
|
||||
mozilla::ErrorResult& rv);
|
||||
void Writeln(const mozilla::dom::Sequence<nsString>& aText,
|
||||
mozilla::ErrorResult& rv);
|
||||
void GetDesignMode(nsAString& aDesignMode);
|
||||
void SetDesignMode(const nsAString& aDesignMode,
|
||||
nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& rv);
|
||||
|
@ -222,19 +205,11 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
|||
|
||||
static void DocumentWriteTerminationFunc(nsISupports* aRef);
|
||||
|
||||
void WriteCommon(const nsAString& aText, bool aNewlineTerminate,
|
||||
mozilla::ErrorResult& aRv);
|
||||
// A version of WriteCommon used by WebIDL bindings
|
||||
void WriteCommon(const mozilla::dom::Sequence<nsString>& aText,
|
||||
bool aNewlineTerminate, mozilla::ErrorResult& rv);
|
||||
|
||||
/**
|
||||
* Like IsEditingOn(), but will flush as needed first.
|
||||
*/
|
||||
bool IsEditingOnAfterFlush();
|
||||
|
||||
void* GenerateParserKey(void);
|
||||
|
||||
// A helper class to keep nsContentList objects alive for a short period of
|
||||
// time. Note, when the final Release is called on an nsContentList object, it
|
||||
// removes itself from MutationObserver list.
|
||||
|
@ -290,19 +265,9 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
|||
*/
|
||||
void MaybeDispatchCheckKeyPressEventModelEvent();
|
||||
|
||||
// Tracks if we are currently processing any document.write calls (either
|
||||
// implicit or explicit). Note that if a write call writes out something which
|
||||
// would block the parser, then mWriteLevel will be incorrect until the parser
|
||||
// finishes processing that script.
|
||||
uint32_t mWriteLevel;
|
||||
|
||||
// Load flags of the document's channel
|
||||
uint32_t mLoadFlags;
|
||||
|
||||
bool mTooDeepWriteRecursion;
|
||||
|
||||
bool mDisableDocWrite;
|
||||
|
||||
bool mWarnedWidthHeight;
|
||||
|
||||
/* Midas implementation */
|
||||
|
|
|
@ -27,11 +27,6 @@ class nsIHTMLDocument : public nsISupports {
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTMLDOCUMENT_IID)
|
||||
|
||||
/**
|
||||
* Set compatibility mode for this document
|
||||
*/
|
||||
virtual void SetCompatibilityMode(nsCompatibility aMode) = 0;
|
||||
|
||||
/**
|
||||
* Called when form->BindToTree() is called so that document knows
|
||||
* immediately when a form is added
|
||||
|
@ -50,8 +45,6 @@ class nsIHTMLDocument : public nsISupports {
|
|||
// not the rest?
|
||||
virtual int32_t GetNumFormsSynchronous() = 0;
|
||||
|
||||
virtual bool IsWriting() = 0;
|
||||
|
||||
/**
|
||||
* Should be called when an element's editable changes as a result of
|
||||
* changing its contentEditable attribute/property.
|
||||
|
@ -99,8 +92,6 @@ class nsIHTMLDocument : public nsISupports {
|
|||
virtual void TearingDownEditor() = 0;
|
||||
|
||||
virtual void SetIsXHTML(bool aXHTML) = 0;
|
||||
|
||||
virtual void SetDocWriteDisabled(bool aDisabled) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLDocument, NS_IHTMLDOCUMENT_IID)
|
||||
|
|
|
@ -144,11 +144,16 @@ partial interface Document {
|
|||
//(Not implemented)readonly attribute DOMElementMap cssElementMap;
|
||||
|
||||
// dynamic markup insertion
|
||||
//(HTML only)Document open(optional DOMString type, optional DOMString replace);
|
||||
//(HTML only)WindowProxy open(DOMString url, DOMString name, DOMString features, optional boolean replace);
|
||||
//(HTML only)void close();
|
||||
//(HTML only)void write(DOMString... text);
|
||||
//(HTML only)void writeln(DOMString... text);
|
||||
[CEReactions, Throws]
|
||||
Document open(optional DOMString type, optional DOMString replace = ""); // type is ignored
|
||||
[CEReactions, Throws]
|
||||
WindowProxy? open(DOMString url, DOMString name, DOMString features, optional boolean replace = false);
|
||||
[CEReactions, Throws]
|
||||
void close();
|
||||
[CEReactions, Throws]
|
||||
void write(DOMString... text);
|
||||
[CEReactions, Throws]
|
||||
void writeln(DOMString... text);
|
||||
|
||||
// user interaction
|
||||
[Pure]
|
||||
|
|
|
@ -10,18 +10,6 @@ interface HTMLDocument : Document {
|
|||
[Throws]
|
||||
getter object (DOMString name);
|
||||
|
||||
// dynamic markup insertion
|
||||
[CEReactions, Throws]
|
||||
Document open(optional DOMString type, optional DOMString replace = ""); // type is ignored
|
||||
[CEReactions, Throws]
|
||||
WindowProxy? open(DOMString url, DOMString name, DOMString features, optional boolean replace = false);
|
||||
[CEReactions, Throws]
|
||||
void close();
|
||||
[CEReactions, Throws]
|
||||
void write(DOMString... text);
|
||||
[CEReactions, Throws]
|
||||
void writeln(DOMString... text);
|
||||
|
||||
[CEReactions, SetterThrows, SetterNeedsSubjectPrincipal]
|
||||
attribute DOMString designMode;
|
||||
[CEReactions, Throws, NeedsSubjectPrincipal]
|
||||
|
|
|
@ -123,7 +123,7 @@ nsresult NS_NewDOMDocument(Document** aInstancePtrResult,
|
|||
if (isHTML) {
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d);
|
||||
NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?");
|
||||
htmlDoc->SetCompatibilityMode(eCompatibility_FullStandards);
|
||||
d->SetCompatibilityMode(eCompatibility_FullStandards);
|
||||
htmlDoc->SetIsXHTML(isXHTML);
|
||||
}
|
||||
d->SetLoadedAsData(aLoadedAsData);
|
||||
|
|
|
@ -322,10 +322,7 @@ NS_IMETHODIMP
|
|||
nsXMLContentSink::OnDocumentCreated(Document* aResultDocument) {
|
||||
NS_ENSURE_ARG(aResultDocument);
|
||||
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aResultDocument);
|
||||
if (htmlDoc) {
|
||||
htmlDoc->SetDocWriteDisabled(true);
|
||||
}
|
||||
aResultDocument->SetDocWriteDisabled(true);
|
||||
|
||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
||||
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
|
||||
|
@ -362,10 +359,7 @@ nsXMLContentSink::OnTransformDone(nsresult aResult, Document* aResultDocument) {
|
|||
}
|
||||
// Transform succeeded, or it failed and we have an error document to display.
|
||||
mDocument = aResultDocument;
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
|
||||
if (htmlDoc) {
|
||||
htmlDoc->SetDocWriteDisabled(false);
|
||||
}
|
||||
aResultDocument->SetDocWriteDisabled(false);
|
||||
|
||||
// Notify document observers that all the content has been stuck
|
||||
// into the document.
|
||||
|
|
|
@ -812,9 +812,8 @@ nsresult txMozillaXMLOutput::createResultDocument(const nsAString& aName,
|
|||
|
||||
// Do this after calling OnDocumentCreated to ensure that the
|
||||
// PresShell/PresContext has been hooked up and get notified.
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
|
||||
if (htmlDoc) {
|
||||
htmlDoc->SetCompatibilityMode(eCompatibility_FullStandards);
|
||||
if (mDocument) {
|
||||
mDocument->SetCompatibilityMode(eCompatibility_FullStandards);
|
||||
}
|
||||
|
||||
// Add a doc-type if requested
|
||||
|
|
|
@ -632,7 +632,7 @@ nsEditingSession::OnStateChange(nsIWebProgress* aWebProgress,
|
|||
RefPtr<Document> doc = piWindow->GetDoc();
|
||||
nsHTMLDocument* htmlDoc =
|
||||
doc && doc->IsHTMLOrXHTML() ? doc->AsHTMLDocument() : nullptr;
|
||||
if (htmlDoc && htmlDoc->IsWriting()) {
|
||||
if (htmlDoc && doc->IsWriting()) {
|
||||
nsAutoString designMode;
|
||||
htmlDoc->GetDesignMode(designMode);
|
||||
|
||||
|
|
|
@ -92,9 +92,7 @@ void nsHtml5DocumentBuilder::SetDocumentMode(nsHtml5DocumentMode m) {
|
|||
mode = eCompatibility_NavQuirks;
|
||||
break;
|
||||
}
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(mDocument);
|
||||
NS_ASSERTION(htmlDocument, "Document didn't QI into HTML document.");
|
||||
htmlDocument->SetCompatibilityMode(mode);
|
||||
mDocument->SetCompatibilityMode(mode);
|
||||
}
|
||||
|
||||
// nsContentSink overrides
|
||||
|
|
|
@ -1,20 +1,5 @@
|
|||
prefs: [dom.security.featurePolicy.enabled:true]
|
||||
[interfaces.https.html?include=(Document|Window)]
|
||||
[Document interface: operation open(DOMString, DOMString)]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: operation open(USVString, DOMString, DOMString)]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: operation close()]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: operation write(DOMString)]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: operation writeln(DOMString)]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: attribute designMode]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -81,33 +66,6 @@ prefs: [dom.security.featurePolicy.enabled:true]
|
|||
[Document interface: iframe.contentDocument must inherit property "onsecuritypolicyviolation" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: new Document() must inherit property "open(DOMString, DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: calling open(DOMString, DOMString) on new Document() with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: new Document() must inherit property "open(USVString, DOMString, DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: calling open(USVString, DOMString, DOMString) on new Document() with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: new Document() must inherit property "close()" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: new Document() must inherit property "write(DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: calling write(DOMString) on new Document() with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: new Document() must inherit property "writeln(DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: calling writeln(DOMString) on new Document() with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: new Document() must inherit property "designMode" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -180,33 +138,6 @@ prefs: [dom.security.featurePolicy.enabled:true]
|
|||
[Document interface: new Document() must inherit property "onsecuritypolicyviolation" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "open(DOMString, DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: calling open(DOMString, DOMString) on document.implementation.createDocument(null, "", null) with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "open(USVString, DOMString, DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: calling open(USVString, DOMString, DOMString) on document.implementation.createDocument(null, "", null) with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "close()" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "write(DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: calling write(DOMString) on document.implementation.createDocument(null, "", null) with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "writeln(DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: calling writeln(DOMString) on document.implementation.createDocument(null, "", null) with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "designMode" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
<hbox class="actionButtons" flex="1">
|
||||
<spacer flex="1"/>
|
||||
#ifndef XP_MACOSX
|
||||
<button oncommand="close();"
|
||||
<button oncommand="window.close();"
|
||||
data-l10n-id="close-button"/>
|
||||
#endif
|
||||
</hbox>
|
||||
|
|
|
@ -42,7 +42,7 @@ class MozFindbar extends XULElement {
|
|||
<image anonid="find-status-icon" class="findbar-find-fast find-status-icon" />
|
||||
<description anonid="find-status" control="findbar-textbox" class="findbar-find-fast findbar-find-status" />
|
||||
</hbox>
|
||||
<toolbarbutton anonid="find-closebutton" class="findbar-closebutton close-icon" data-l10n-id="findbar-find-button-close" oncommand="close();" />
|
||||
<toolbarbutton anonid="find-closebutton" class="findbar-closebutton close-icon" data-l10n-id="findbar-find-button-close" oncommand="window.close();" />
|
||||
`);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче