forked from mirrors/gecko-dev
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:
parent
0f77590986
commit
ad6a833e39
24 changed files with 583 additions and 667 deletions
|
|
@ -95,7 +95,7 @@
|
||||||
<keyset id="placesOrganizerKeyset">
|
<keyset id="placesOrganizerKeyset">
|
||||||
<!-- Instantiation Keys -->
|
<!-- Instantiation Keys -->
|
||||||
<key id="placesKey_close" key="&cmd.close.key;" modifiers="accel"
|
<key id="placesKey_close" key="&cmd.close.key;" modifiers="accel"
|
||||||
oncommand="close();"/>
|
oncommand="window.close();"/>
|
||||||
|
|
||||||
<!-- Command Keys -->
|
<!-- Command Keys -->
|
||||||
<key id="placesKey_find:all"
|
<key id="placesKey_find:all"
|
||||||
|
|
@ -247,7 +247,7 @@
|
||||||
key="placesKey_close"
|
key="placesKey_close"
|
||||||
label="&file.close.label;"
|
label="&file.close.label;"
|
||||||
accesskey="&file.close.accesskey;"
|
accesskey="&file.close.accesskey;"
|
||||||
oncommand="close();"/>
|
oncommand="window.close();"/>
|
||||||
#endif
|
#endif
|
||||||
</menupopup>
|
</menupopup>
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
||||||
<hbox class="actionButtons" align="right" flex="1">
|
<hbox class="actionButtons" align="right" flex="1">
|
||||||
<button oncommand="close();" icon="close"
|
<button oncommand="window.close();" icon="close"
|
||||||
data-l10n-id="blocklist-button-cancel"/>
|
data-l10n-id="blocklist-button-cancel"/>
|
||||||
<button id="btnApplyChanges" oncommand="gBlocklistManager.onApplyChanges();" icon="save"
|
<button id="btnApplyChanges" oncommand="gBlocklistManager.onApplyChanges();" icon="save"
|
||||||
data-l10n-id="blocklist-button-ok"/>
|
data-l10n-id="blocklist-button-ok"/>
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
<spacer flex="1"/>
|
<spacer flex="1"/>
|
||||||
<hbox class="actionButtons" align="right" flex="1">
|
<hbox class="actionButtons" align="right" flex="1">
|
||||||
<button id="butCancel"
|
<button id="butCancel"
|
||||||
oncommand="close(event);"
|
oncommand="window.close(event);"
|
||||||
class="syncDisconnectButton"
|
class="syncDisconnectButton"
|
||||||
data-l10n-id="sync-disconnect-cancel"/>
|
data-l10n-id="sync-disconnect-cancel"/>
|
||||||
<button id="butDisconnect"
|
<button id="butDisconnect"
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,6 @@
|
||||||
|
|
||||||
<separator class="thin"/>
|
<separator class="thin"/>
|
||||||
|
|
||||||
<button oncommand="close();" icon="close" label="Close" />
|
<button oncommand="window.close();" icon="close" label="Close" />
|
||||||
|
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,6 @@
|
||||||
|
|
||||||
<separator class="thin"/>
|
<separator class="thin"/>
|
||||||
|
|
||||||
<button oncommand="close();" icon="close" label="Close" />
|
<button oncommand="window.close();" icon="close" label="Close" />
|
||||||
|
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
</hbox>
|
</hbox>
|
||||||
<spacer flex="1"/>
|
<spacer flex="1"/>
|
||||||
<hbox class="actionButtons" align="right" 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" />
|
data-l10n-id="permissions-button-cancel" />
|
||||||
<button id="btnApplyChanges" oncommand="gPermissionManager.onApplyChanges();" icon="save"
|
<button id="btnApplyChanges" oncommand="gPermissionManager.onApplyChanges();" icon="save"
|
||||||
data-l10n-id="permissions-button-ok" />
|
data-l10n-id="permissions-button-ok" />
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@
|
||||||
data-l10n-id="disable-extension"/>
|
data-l10n-id="disable-extension"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
<hbox class="actionButtons" align="right" flex="1">
|
<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" />
|
data-l10n-id="permissions-button-cancel" />
|
||||||
<button id="btnApplyChanges" oncommand="gSitePermissionsManager.onApplyChanges();" icon="save"
|
<button id="btnApplyChanges" oncommand="gSitePermissionsManager.onApplyChanges();" icon="save"
|
||||||
data-l10n-id="permissions-button-ok" />
|
data-l10n-id="permissions-button-ok" />
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
icon="clear"
|
icon="clear"
|
||||||
oncommand="gTranslationExceptions.onAllSitesDeleted();"/>
|
oncommand="gTranslationExceptions.onAllSitesDeleted();"/>
|
||||||
<spacer flex="1"/>
|
<spacer flex="1"/>
|
||||||
<button oncommand="close();" icon="close"
|
<button oncommand="window.close();" icon="close"
|
||||||
data-l10n-id="translation-button-close"/>
|
data-l10n-id="translation-button-close"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
</window>
|
</window>
|
||||||
|
|
|
||||||
|
|
@ -313,12 +313,16 @@
|
||||||
#include "StorageAccessPermissionRequest.h"
|
#include "StorageAccessPermissionRequest.h"
|
||||||
#include "mozilla/dom/WindowProxyHolder.h"
|
#include "mozilla/dom/WindowProxyHolder.h"
|
||||||
#include "ThirdPartyUtil.h"
|
#include "ThirdPartyUtil.h"
|
||||||
|
#include "nsHtml5Module.h"
|
||||||
|
#include "nsHtml5Parser.h"
|
||||||
|
|
||||||
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
|
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
|
||||||
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
|
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
|
||||||
#define XML_DECLARATION_BITS_STANDALONE_EXISTS (1 << 2)
|
#define XML_DECLARATION_BITS_STANDALONE_EXISTS (1 << 2)
|
||||||
#define XML_DECLARATION_BITS_STANDALONE_YES (1 << 3)
|
#define XML_DECLARATION_BITS_STANDALONE_YES (1 << 3)
|
||||||
|
|
||||||
|
#define NS_MAX_DOCUMENT_WRITE_DEPTH 20
|
||||||
|
|
||||||
extern bool sDisablePrefetchHTTPSPref;
|
extern bool sDisablePrefetchHTTPSPref;
|
||||||
|
|
||||||
mozilla::LazyLogModule gPageCacheLog("PageCache");
|
mozilla::LazyLogModule gPageCacheLog("PageCache");
|
||||||
|
|
@ -1251,10 +1255,13 @@ Document::Document(const char* aContentType)
|
||||||
mLoadEventFiring(false),
|
mLoadEventFiring(false),
|
||||||
mSkipLoadEventAfterClose(false),
|
mSkipLoadEventAfterClose(false),
|
||||||
mDisableCookieAccess(false),
|
mDisableCookieAccess(false),
|
||||||
|
mDisableDocWrite(false),
|
||||||
|
mTooDeepWriteRecursion(false),
|
||||||
mPendingFullscreenRequests(0),
|
mPendingFullscreenRequests(0),
|
||||||
mXMLDeclarationBits(0),
|
mXMLDeclarationBits(0),
|
||||||
mOnloadBlockCount(0),
|
mOnloadBlockCount(0),
|
||||||
mAsyncOnloadBlockCount(0),
|
mAsyncOnloadBlockCount(0),
|
||||||
|
mWriteLevel(0),
|
||||||
mCompatMode(eCompatibility_FullStandards),
|
mCompatMode(eCompatibility_FullStandards),
|
||||||
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
|
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
|
||||||
mAncestorIsLoading(false),
|
mAncestorIsLoading(false),
|
||||||
|
|
@ -2519,6 +2526,17 @@ void Document::CompatibilityModeChanged() {
|
||||||
ApplicableStylesChanged();
|
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,
|
static void WarnIfSandboxIneffective(nsIDocShell* aDocShell,
|
||||||
uint32_t aSandboxFlags,
|
uint32_t aSandboxFlags,
|
||||||
nsIChannel* aChannel) {
|
nsIChannel* aChannel) {
|
||||||
|
|
@ -6709,6 +6727,485 @@ nsIHTMLCollection* Document::Anchors() {
|
||||||
return mAnchors;
|
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 */
|
/* static */
|
||||||
bool Document::MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
|
bool Document::MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
|
||||||
nsAtom* aAtom, void* aData) {
|
nsAtom* aAtom, void* aData) {
|
||||||
|
|
|
||||||
|
|
@ -1280,6 +1280,22 @@ class Document : public nsINode,
|
||||||
*/
|
*/
|
||||||
void DisableCookieAccess() { mDisableCookieAccess = true; }
|
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
|
* Access HTTP header data (this may also get set from other
|
||||||
* sources, like HTML META tags).
|
* sources, like HTML META tags).
|
||||||
|
|
@ -3289,6 +3305,16 @@ class Document : public nsINode,
|
||||||
return GetFuncStringContentList<nsCachableElementsByNameNodeList>(
|
return GetFuncStringContentList<nsCachableElementsByNameNodeList>(
|
||||||
this, MatchNameAttribute, nullptr, UseExistingNameString, aName);
|
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;
|
Nullable<WindowProxyHolder> GetDefaultView() const;
|
||||||
Element* GetActiveElement();
|
Element* GetActiveElement();
|
||||||
bool HasFocus(ErrorResult& rv) const;
|
bool HasFocus(ErrorResult& rv) const;
|
||||||
|
|
@ -3916,6 +3942,14 @@ class Document : public nsINode,
|
||||||
already_AddRefed<nsIURI> RegistrableDomainSuffixOfInternal(
|
already_AddRefed<nsIURI> RegistrableDomainSuffixOfInternal(
|
||||||
const nsAString& aHostSuffixString, nsIURI* aOrigHost);
|
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:
|
private:
|
||||||
void RecordContentBlockingLog(
|
void RecordContentBlockingLog(
|
||||||
const nsACString& aOrigin, uint32_t aType, bool aBlocked,
|
const nsACString& aOrigin, uint32_t aType, bool aBlocked,
|
||||||
|
|
@ -4388,6 +4422,13 @@ class Document : public nsINode,
|
||||||
// When false, the .cookies property is completely disabled
|
// When false, the .cookies property is completely disabled
|
||||||
bool mDisableCookieAccess : 1;
|
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 mPendingFullscreenRequests;
|
||||||
|
|
||||||
uint8_t mXMLDeclarationBits;
|
uint8_t mXMLDeclarationBits;
|
||||||
|
|
@ -4398,6 +4439,12 @@ class Document : public nsINode,
|
||||||
// Onload blockers which haven't been activated yet.
|
// Onload blockers which haven't been activated yet.
|
||||||
uint32_t mAsyncOnloadBlockCount;
|
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
|
// Compatibility mode
|
||||||
nsCompatibility mCompatMode;
|
nsCompatibility mCompatMode;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -660,20 +660,18 @@ NS_IMETHODIMP
|
||||||
HTMLContentSink::WillBuildModel(nsDTDMode aDTDMode) {
|
HTMLContentSink::WillBuildModel(nsDTDMode aDTDMode) {
|
||||||
WillBuildModelImpl();
|
WillBuildModelImpl();
|
||||||
|
|
||||||
if (mHTMLDocument) {
|
nsCompatibility mode = eCompatibility_NavQuirks;
|
||||||
nsCompatibility mode = eCompatibility_NavQuirks;
|
switch (aDTDMode) {
|
||||||
switch (aDTDMode) {
|
case eDTDMode_full_standards:
|
||||||
case eDTDMode_full_standards:
|
mode = eCompatibility_FullStandards;
|
||||||
mode = eCompatibility_FullStandards;
|
break;
|
||||||
break;
|
case eDTDMode_almost_standards:
|
||||||
case eDTDMode_almost_standards:
|
mode = eCompatibility_AlmostStandards;
|
||||||
mode = eCompatibility_AlmostStandards;
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
mHTMLDocument->SetCompatibilityMode(mode);
|
|
||||||
}
|
}
|
||||||
|
mDocument->SetCompatibilityMode(mode);
|
||||||
|
|
||||||
// Notify document that the load is beginning
|
// Notify document that the load is beginning
|
||||||
mDocument->BeginLoad();
|
mDocument->BeginLoad();
|
||||||
|
|
|
||||||
|
|
@ -120,8 +120,6 @@
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
#define NS_MAX_DOCUMENT_WRITE_DEPTH 20
|
|
||||||
|
|
||||||
#include "prtime.h"
|
#include "prtime.h"
|
||||||
|
|
||||||
//#define DEBUG_charset
|
//#define DEBUG_charset
|
||||||
|
|
@ -171,10 +169,7 @@ nsHTMLDocument::nsHTMLDocument()
|
||||||
: Document("text/html"),
|
: Document("text/html"),
|
||||||
mContentListHolder(nullptr),
|
mContentListHolder(nullptr),
|
||||||
mNumForms(0),
|
mNumForms(0),
|
||||||
mWriteLevel(0),
|
|
||||||
mLoadFlags(0),
|
mLoadFlags(0),
|
||||||
mTooDeepWriteRecursion(false),
|
|
||||||
mDisableDocWrite(false),
|
|
||||||
mWarnedWidthHeight(false),
|
mWarnedWidthHeight(false),
|
||||||
mContentEditableCount(0),
|
mContentEditableCount(0),
|
||||||
mEditingState(EditingState::eOff),
|
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 {
|
bool nsHTMLDocument::UseWidthDeviceWidthFallbackViewport() const {
|
||||||
if (mIsPlainText) {
|
if (mIsPlainText) {
|
||||||
// Plain text documents are simple enough that font inflation doesn't offer
|
// Plain text documents are simple enough that font inflation doesn't offer
|
||||||
|
|
@ -801,465 +785,6 @@ bool nsHTMLDocument::IsRegistrableDomainSuffixOfOrEqualTo(
|
||||||
return true;
|
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::AddedForm() { ++mNumForms; }
|
||||||
|
|
||||||
void nsHTMLDocument::RemovedForm() { --mNumForms; }
|
void nsHTMLDocument::RemovedForm() { --mNumForms; }
|
||||||
|
|
@ -1417,28 +942,6 @@ bool nsHTMLDocument::MatchFormControls(Element* aElement, int32_t aNamespaceID,
|
||||||
return aElement->IsNodeOfType(nsIContent::eHTML_FORM_CONTROL);
|
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) {
|
void nsHTMLDocument::GetDesignMode(nsAString& aDesignMode) {
|
||||||
if (HasFlag(NODE_IS_EDITABLE)) {
|
if (HasFlag(NODE_IS_EDITABLE)) {
|
||||||
aDesignMode.AssignLiteral("on");
|
aDesignMode.AssignLiteral("on");
|
||||||
|
|
|
||||||
|
|
@ -74,10 +74,6 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// nsIHTMLDocument
|
// nsIHTMLDocument
|
||||||
virtual void SetCompatibilityMode(nsCompatibility aMode) override;
|
|
||||||
|
|
||||||
virtual bool IsWriting() override { return mWriteLevel != uint32_t(0); }
|
|
||||||
|
|
||||||
virtual Element* GetUnfocusedKeyEventTarget() override;
|
virtual Element* GetUnfocusedKeyEventTarget() override;
|
||||||
|
|
||||||
nsContentList* GetExistingForms() const { return mForms; }
|
nsContentList* GetExistingForms() const { return mForms; }
|
||||||
|
|
@ -96,9 +92,6 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
||||||
virtual void SetIsXHTML(bool aXHTML) override {
|
virtual void SetIsXHTML(bool aXHTML) override {
|
||||||
mType = (aXHTML ? eXHTML : eHTML);
|
mType = (aXHTML ? eXHTML : eHTML);
|
||||||
}
|
}
|
||||||
virtual void SetDocWriteDisabled(bool aDisabled) override {
|
|
||||||
mDisableDocWrite = aDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult ChangeContentEditableCount(nsIContent* aElement,
|
nsresult ChangeContentEditableCount(nsIContent* aElement,
|
||||||
int32_t aChange) override;
|
int32_t aChange) override;
|
||||||
|
|
@ -152,16 +145,6 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GetSupportedNames(nsTArray<nsString>& aNames);
|
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 GetDesignMode(nsAString& aDesignMode);
|
||||||
void SetDesignMode(const nsAString& aDesignMode,
|
void SetDesignMode(const nsAString& aDesignMode,
|
||||||
nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& rv);
|
nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& rv);
|
||||||
|
|
@ -222,19 +205,11 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
||||||
|
|
||||||
static void DocumentWriteTerminationFunc(nsISupports* aRef);
|
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.
|
* Like IsEditingOn(), but will flush as needed first.
|
||||||
*/
|
*/
|
||||||
bool IsEditingOnAfterFlush();
|
bool IsEditingOnAfterFlush();
|
||||||
|
|
||||||
void* GenerateParserKey(void);
|
|
||||||
|
|
||||||
// A helper class to keep nsContentList objects alive for a short period of
|
// 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
|
// time. Note, when the final Release is called on an nsContentList object, it
|
||||||
// removes itself from MutationObserver list.
|
// removes itself from MutationObserver list.
|
||||||
|
|
@ -290,19 +265,9 @@ class nsHTMLDocument : public mozilla::dom::Document, public nsIHTMLDocument {
|
||||||
*/
|
*/
|
||||||
void MaybeDispatchCheckKeyPressEventModelEvent();
|
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
|
// Load flags of the document's channel
|
||||||
uint32_t mLoadFlags;
|
uint32_t mLoadFlags;
|
||||||
|
|
||||||
bool mTooDeepWriteRecursion;
|
|
||||||
|
|
||||||
bool mDisableDocWrite;
|
|
||||||
|
|
||||||
bool mWarnedWidthHeight;
|
bool mWarnedWidthHeight;
|
||||||
|
|
||||||
/* Midas implementation */
|
/* Midas implementation */
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,6 @@ class nsIHTMLDocument : public nsISupports {
|
||||||
public:
|
public:
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTMLDOCUMENT_IID)
|
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
|
* Called when form->BindToTree() is called so that document knows
|
||||||
* immediately when a form is added
|
* immediately when a form is added
|
||||||
|
|
@ -50,8 +45,6 @@ class nsIHTMLDocument : public nsISupports {
|
||||||
// not the rest?
|
// not the rest?
|
||||||
virtual int32_t GetNumFormsSynchronous() = 0;
|
virtual int32_t GetNumFormsSynchronous() = 0;
|
||||||
|
|
||||||
virtual bool IsWriting() = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should be called when an element's editable changes as a result of
|
* Should be called when an element's editable changes as a result of
|
||||||
* changing its contentEditable attribute/property.
|
* changing its contentEditable attribute/property.
|
||||||
|
|
@ -99,8 +92,6 @@ class nsIHTMLDocument : public nsISupports {
|
||||||
virtual void TearingDownEditor() = 0;
|
virtual void TearingDownEditor() = 0;
|
||||||
|
|
||||||
virtual void SetIsXHTML(bool aXHTML) = 0;
|
virtual void SetIsXHTML(bool aXHTML) = 0;
|
||||||
|
|
||||||
virtual void SetDocWriteDisabled(bool aDisabled) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLDocument, NS_IHTMLDOCUMENT_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLDocument, NS_IHTMLDOCUMENT_IID)
|
||||||
|
|
|
||||||
|
|
@ -144,11 +144,16 @@ partial interface Document {
|
||||||
//(Not implemented)readonly attribute DOMElementMap cssElementMap;
|
//(Not implemented)readonly attribute DOMElementMap cssElementMap;
|
||||||
|
|
||||||
// dynamic markup insertion
|
// dynamic markup insertion
|
||||||
//(HTML only)Document open(optional DOMString type, optional DOMString replace);
|
[CEReactions, Throws]
|
||||||
//(HTML only)WindowProxy open(DOMString url, DOMString name, DOMString features, optional boolean replace);
|
Document open(optional DOMString type, optional DOMString replace = ""); // type is ignored
|
||||||
//(HTML only)void close();
|
[CEReactions, Throws]
|
||||||
//(HTML only)void write(DOMString... text);
|
WindowProxy? open(DOMString url, DOMString name, DOMString features, optional boolean replace = false);
|
||||||
//(HTML only)void writeln(DOMString... text);
|
[CEReactions, Throws]
|
||||||
|
void close();
|
||||||
|
[CEReactions, Throws]
|
||||||
|
void write(DOMString... text);
|
||||||
|
[CEReactions, Throws]
|
||||||
|
void writeln(DOMString... text);
|
||||||
|
|
||||||
// user interaction
|
// user interaction
|
||||||
[Pure]
|
[Pure]
|
||||||
|
|
|
||||||
|
|
@ -10,18 +10,6 @@ interface HTMLDocument : Document {
|
||||||
[Throws]
|
[Throws]
|
||||||
getter object (DOMString name);
|
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]
|
[CEReactions, SetterThrows, SetterNeedsSubjectPrincipal]
|
||||||
attribute DOMString designMode;
|
attribute DOMString designMode;
|
||||||
[CEReactions, Throws, NeedsSubjectPrincipal]
|
[CEReactions, Throws, NeedsSubjectPrincipal]
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ nsresult NS_NewDOMDocument(Document** aInstancePtrResult,
|
||||||
if (isHTML) {
|
if (isHTML) {
|
||||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d);
|
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d);
|
||||||
NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?");
|
NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?");
|
||||||
htmlDoc->SetCompatibilityMode(eCompatibility_FullStandards);
|
d->SetCompatibilityMode(eCompatibility_FullStandards);
|
||||||
htmlDoc->SetIsXHTML(isXHTML);
|
htmlDoc->SetIsXHTML(isXHTML);
|
||||||
}
|
}
|
||||||
d->SetLoadedAsData(aLoadedAsData);
|
d->SetLoadedAsData(aLoadedAsData);
|
||||||
|
|
|
||||||
|
|
@ -322,10 +322,7 @@ NS_IMETHODIMP
|
||||||
nsXMLContentSink::OnDocumentCreated(Document* aResultDocument) {
|
nsXMLContentSink::OnDocumentCreated(Document* aResultDocument) {
|
||||||
NS_ENSURE_ARG(aResultDocument);
|
NS_ENSURE_ARG(aResultDocument);
|
||||||
|
|
||||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aResultDocument);
|
aResultDocument->SetDocWriteDisabled(true);
|
||||||
if (htmlDoc) {
|
|
||||||
htmlDoc->SetDocWriteDisabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
nsCOMPtr<nsIContentViewer> contentViewer;
|
||||||
mDocShell->GetContentViewer(getter_AddRefs(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.
|
// Transform succeeded, or it failed and we have an error document to display.
|
||||||
mDocument = aResultDocument;
|
mDocument = aResultDocument;
|
||||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
|
aResultDocument->SetDocWriteDisabled(false);
|
||||||
if (htmlDoc) {
|
|
||||||
htmlDoc->SetDocWriteDisabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify document observers that all the content has been stuck
|
// Notify document observers that all the content has been stuck
|
||||||
// into the document.
|
// into the document.
|
||||||
|
|
|
||||||
|
|
@ -812,9 +812,8 @@ nsresult txMozillaXMLOutput::createResultDocument(const nsAString& aName,
|
||||||
|
|
||||||
// Do this after calling OnDocumentCreated to ensure that the
|
// Do this after calling OnDocumentCreated to ensure that the
|
||||||
// PresShell/PresContext has been hooked up and get notified.
|
// PresShell/PresContext has been hooked up and get notified.
|
||||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
|
if (mDocument) {
|
||||||
if (htmlDoc) {
|
mDocument->SetCompatibilityMode(eCompatibility_FullStandards);
|
||||||
htmlDoc->SetCompatibilityMode(eCompatibility_FullStandards);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a doc-type if requested
|
// Add a doc-type if requested
|
||||||
|
|
|
||||||
|
|
@ -632,7 +632,7 @@ nsEditingSession::OnStateChange(nsIWebProgress* aWebProgress,
|
||||||
RefPtr<Document> doc = piWindow->GetDoc();
|
RefPtr<Document> doc = piWindow->GetDoc();
|
||||||
nsHTMLDocument* htmlDoc =
|
nsHTMLDocument* htmlDoc =
|
||||||
doc && doc->IsHTMLOrXHTML() ? doc->AsHTMLDocument() : nullptr;
|
doc && doc->IsHTMLOrXHTML() ? doc->AsHTMLDocument() : nullptr;
|
||||||
if (htmlDoc && htmlDoc->IsWriting()) {
|
if (htmlDoc && doc->IsWriting()) {
|
||||||
nsAutoString designMode;
|
nsAutoString designMode;
|
||||||
htmlDoc->GetDesignMode(designMode);
|
htmlDoc->GetDesignMode(designMode);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,7 @@ void nsHtml5DocumentBuilder::SetDocumentMode(nsHtml5DocumentMode m) {
|
||||||
mode = eCompatibility_NavQuirks;
|
mode = eCompatibility_NavQuirks;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(mDocument);
|
mDocument->SetCompatibilityMode(mode);
|
||||||
NS_ASSERTION(htmlDocument, "Document didn't QI into HTML document.");
|
|
||||||
htmlDocument->SetCompatibilityMode(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsContentSink overrides
|
// nsContentSink overrides
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,5 @@
|
||||||
prefs: [dom.security.featurePolicy.enabled:true]
|
prefs: [dom.security.featurePolicy.enabled:true]
|
||||||
[interfaces.https.html?include=(Document|Window)]
|
[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]
|
[Document interface: attribute designMode]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
@ -81,33 +66,6 @@ prefs: [dom.security.featurePolicy.enabled:true]
|
||||||
[Document interface: iframe.contentDocument must inherit property "onsecuritypolicyviolation" with the proper type]
|
[Document interface: iframe.contentDocument must inherit property "onsecuritypolicyviolation" with the proper type]
|
||||||
expected: FAIL
|
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]
|
[Document interface: new Document() must inherit property "designMode" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
@ -180,33 +138,6 @@ prefs: [dom.security.featurePolicy.enabled:true]
|
||||||
[Document interface: new Document() must inherit property "onsecuritypolicyviolation" with the proper type]
|
[Document interface: new Document() must inherit property "onsecuritypolicyviolation" with the proper type]
|
||||||
expected: FAIL
|
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]
|
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "designMode" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@
|
||||||
<hbox class="actionButtons" flex="1">
|
<hbox class="actionButtons" flex="1">
|
||||||
<spacer flex="1"/>
|
<spacer flex="1"/>
|
||||||
#ifndef XP_MACOSX
|
#ifndef XP_MACOSX
|
||||||
<button oncommand="close();"
|
<button oncommand="window.close();"
|
||||||
data-l10n-id="close-button"/>
|
data-l10n-id="close-button"/>
|
||||||
#endif
|
#endif
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class MozFindbar extends XULElement {
|
||||||
<image anonid="find-status-icon" class="findbar-find-fast find-status-icon" />
|
<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" />
|
<description anonid="find-status" control="findbar-textbox" class="findbar-find-fast findbar-find-status" />
|
||||||
</hbox>
|
</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();" />
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue