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:
Ehsan Akhgari 2019-05-27 23:03:03 +00:00
Родитель 0f77590986
Коммит ad6a833e39
24 изменённых файлов: 583 добавлений и 667 удалений

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

@ -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();" />
`);
}