NS_IMETHODIMP ImportLoader::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) { AutoError ae(this); nsIPrincipal* principal = Principal(); nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); if (!channel) { return NS_ERROR_DOM_ABORT_ERR; } if (nsContentUtils::IsSystemPrincipal(principal)) { // We should never import non-system documents and run their scripts with system principal! nsCOMPtr<nsIPrincipal> channelPrincipal; nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(channel, getter_AddRefs(channelPrincipal)); if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) { return NS_ERROR_FAILURE; } } channel->SetOwner(principal); nsAutoCString type; channel->GetContentType(type); if (!type.EqualsLiteral("text/html")) { NS_WARNING("ImportLoader wrong content type"); return NS_ERROR_DOM_ABORT_ERR; } // The scope object is same for all the imports in an import tree, // let's get it form the import parent. nsCOMPtr<nsIGlobalObject> global = mImportParent->GetScopeObject(); nsCOMPtr<nsIDOMDocument> importDoc; nsCOMPtr<nsIURI> baseURI = mImportParent->GetBaseURI(); const nsAString& emptyStr = EmptyString(); nsresult rv = NS_NewDOMDocument(getter_AddRefs(importDoc), emptyStr, emptyStr, nullptr, mURI, baseURI, principal, false, global, DocumentFlavorHTML); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR); // The imported document must know which master document it belongs to. mDocument = do_QueryInterface(importDoc); nsCOMPtr<nsIDocument> master = mImportParent->MasterDocument(); mDocument->SetMasterDocument(master); // We want to inherit the sandbox flags and fullscreen enabled flag // from the master document. mDocument->SetSandboxFlags(master->GetSandboxFlags()); // We have to connect the blank document we created with the channel we opened, // and create its own LoadGroup for it. nsCOMPtr<nsIStreamListener> listener; nsCOMPtr<nsILoadGroup> loadGroup; channel->GetLoadGroup(getter_AddRefs(loadGroup)); nsCOMPtr<nsILoadGroup> newLoadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID); NS_ENSURE_TRUE(newLoadGroup, NS_ERROR_OUT_OF_MEMORY); newLoadGroup->SetLoadGroup(loadGroup); rv = mDocument->StartDocumentLoad("import", channel, newLoadGroup, nullptr, getter_AddRefs(listener), true); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR); nsCOMPtr<nsIURI> originalURI; rv = channel->GetOriginalURI(getter_AddRefs(originalURI)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR); nsCOMPtr<nsIURI> URI; rv = channel->GetURI(getter_AddRefs(URI)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR); MOZ_ASSERT(URI, "URI of a channel should never be null"); bool equals; rv = URI->Equals(originalURI, &equals); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR); if (!equals) { // In case of a redirection we must add the new URI to the import map. Manager()->AddLoaderWithNewURI(this, URI); } // Let's start the parser. mParserStreamListener = listener; rv = listener->OnStartRequest(aRequest, aContext); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR); ae.Pass(); return NS_OK; }
/*--------------------------------------------------------------------------- OnStateChange ----------------------------------------------------------------------------*/ NS_IMETHODIMP nsEditingSession::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus) { #ifdef NOISY_DOC_LOADING nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); if (channel) { nsCAutoString contentType; channel->GetContentType(contentType); if (!contentType.IsEmpty()) printf(" ++++++ MIMETYPE = %s\n", contentType.get()); } #endif // // A Request has started... // if (aStateFlags & nsIWebProgressListener::STATE_START) { #ifdef NOISY_DOC_LOADING { nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); if (channel) { nsCOMPtr<nsIURI> uri; channel->GetURI(getter_AddRefs(uri)); if (uri) { nsXPIDLCString spec; uri->GetSpec(spec); printf(" **** STATE_START: CHANNEL URI=%s, flags=%x\n", spec.get(), aStateFlags); } } else printf(" STATE_START: NO CHANNEL flags=%x\n", aStateFlags); } #endif // Page level notification... if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) { nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); StartPageLoad(channel); #ifdef NOISY_DOC_LOADING printf("STATE_START & STATE_IS_NETWORK flags=%x\n", aStateFlags); #endif } // Document level notification... if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT && !(aStateFlags & nsIWebProgressListener::STATE_RESTORING)) { #ifdef NOISY_DOC_LOADING printf("STATE_START & STATE_IS_DOCUMENT flags=%x\n", aStateFlags); #endif bool progressIsForTargetDocument = IsProgressForTargetDocument(aWebProgress); if (progressIsForTargetDocument) { nsCOMPtr<nsIDOMWindow> window; aWebProgress->GetDOMWindow(getter_AddRefs(window)); nsCOMPtr<nsIDOMDocument> doc; window->GetDocument(getter_AddRefs(doc)); nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(doc)); if (htmlDoc && htmlDoc->IsWriting()) { nsCOMPtr<nsIDOMHTMLDocument> htmlDomDoc = do_QueryInterface(doc); nsAutoString designMode; htmlDomDoc->GetDesignMode(designMode); if (designMode.EqualsLiteral("on")) { // This notification is for data coming in through // document.open/write/close(), ignore it. return NS_OK; } } mCanCreateEditor = true; StartDocumentLoad(aWebProgress, progressIsForTargetDocument); } } } // // A Request is being processed // else if (aStateFlags & nsIWebProgressListener::STATE_TRANSFERRING) { if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) { // document transfer started } } // // Got a redirection // else if (aStateFlags & nsIWebProgressListener::STATE_REDIRECTING) { if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) { // got a redirect } } // // A network or document Request has finished... // else if (aStateFlags & nsIWebProgressListener::STATE_STOP) { #ifdef NOISY_DOC_LOADING { nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); if (channel) { nsCOMPtr<nsIURI> uri; channel->GetURI(getter_AddRefs(uri)); if (uri) { nsXPIDLCString spec; uri->GetSpec(spec); printf(" **** STATE_STOP: CHANNEL URI=%s, flags=%x\n", spec.get(), aStateFlags); } } else printf(" STATE_STOP: NO CHANNEL flags=%x\n", aStateFlags); } #endif // Document level notification... if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) { nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); EndDocumentLoad(aWebProgress, channel, aStatus, IsProgressForTargetDocument(aWebProgress)); #ifdef NOISY_DOC_LOADING printf("STATE_STOP & STATE_IS_DOCUMENT flags=%x\n", aStateFlags); #endif } // Page level notification... if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) { nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); (void)EndPageLoad(aWebProgress, channel, aStatus); #ifdef NOISY_DOC_LOADING printf("STATE_STOP & STATE_IS_NETWORK flags=%x\n", aStateFlags); #endif } } return NS_OK; }
NS_IMETHODIMP nsXMLDocument::Load(const nsAString& aUrl, bool *aReturn) { bool hasHadScriptObject = true; nsIScriptGlobalObject* scriptObject = GetScriptHandlingObject(hasHadScriptObject); NS_ENSURE_STATE(scriptObject || !hasHadScriptObject); ReportUseOfDeprecatedMethod(this, "UseOfDOM3LoadMethodWarning"); NS_ENSURE_ARG_POINTER(aReturn); *aReturn = false; nsCOMPtr<nsIDocument> callingDoc = do_QueryInterface(nsContentUtils::GetDocumentFromContext()); nsIURI *baseURI = mDocumentURI; nsAutoCString charset; if (callingDoc) { baseURI = callingDoc->GetDocBaseURI(); charset = callingDoc->GetDocumentCharacterSet(); } // Create a new URI nsCOMPtr<nsIURI> uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, charset.get(), baseURI); if (NS_FAILED(rv)) { return rv; } // Check to see whether the current document is allowed to load this URI. // It's important to use the current document's principal for this check so // that we don't end up in a case where code with elevated privileges is // calling us and changing the principal of this document. // Enforce same-origin even for chrome loaders to avoid someone accidentally // using a document that content has a reference to and turn that into a // chrome document. nsCOMPtr<nsIPrincipal> principal = NodePrincipal(); if (!nsContentUtils::IsSystemPrincipal(principal)) { rv = principal->CheckMayLoad(uri, false, false); NS_ENSURE_SUCCESS(rv, rv); int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XMLHTTPREQUEST, uri, principal, callingDoc ? callingDoc.get() : static_cast<nsIDocument*>(this), NS_LITERAL_CSTRING("application/xml"), nullptr, &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); NS_ENSURE_SUCCESS(rv, rv); if (NS_CP_REJECTED(shouldLoad)) { return NS_ERROR_CONTENT_BLOCKED; } } else { // We're called from chrome, check to make sure the URI we're // about to load is also chrome. bool isChrome = false; if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) { nsAutoCString spec; if (mDocumentURI) mDocumentURI->GetSpec(spec); nsAutoString error; error.AssignLiteral("Cross site loading using document.load is no " "longer supported. Use XMLHttpRequest instead."); nsCOMPtr<nsIScriptError> errorObject = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = errorObject->InitWithWindowID(error, NS_ConvertUTF8toUTF16(spec), EmptyString(), 0, 0, nsIScriptError::warningFlag, "DOM", callingDoc ? callingDoc->InnerWindowID() : this->InnerWindowID()); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID); if (consoleService) { consoleService->LogMessage(errorObject); } return NS_ERROR_DOM_SECURITY_ERR; } } // Partial Reset, need to restore principal for security reasons and // event listener manager so that load listeners etc. will // remain. This should be done before the security check is done to // ensure that the document is reset even if the new document can't // be loaded. Note that we need to hold a strong ref to |principal| // here, because ResetToURI will null out our node principal before // setting the new one. nsRefPtr<nsEventListenerManager> elm(mListenerManager); mListenerManager = nullptr; // When we are called from JS we can find the load group for the page, // and add ourselves to it. This way any pending requests // will be automatically aborted if the user leaves the page. nsCOMPtr<nsILoadGroup> loadGroup; if (callingDoc) { loadGroup = callingDoc->GetDocumentLoadGroup(); } ResetToURI(uri, loadGroup, principal); mListenerManager = elm; // Create a channel nsCOMPtr<nsIInterfaceRequestor> req = nsContentUtils::GetSameOriginChecker(); NS_ENSURE_TRUE(req, NS_ERROR_OUT_OF_MEMORY); nsCOMPtr<nsIChannel> channel; // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, // which in turn keeps STOP button from becoming active rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, loadGroup, req, nsIRequest::LOAD_BACKGROUND); if (NS_FAILED(rv)) { return rv; } // StartDocumentLoad asserts that readyState is uninitialized, so // uninitialize it. SetReadyStateInternal make this transition invisible to // Web content. But before doing that, assert that the current readyState // is complete as it should be after the call to ResetToURI() above. MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE, "Bad readyState"); SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED); // Prepare for loading the XML document "into oneself" nsCOMPtr<nsIStreamListener> listener; if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel, loadGroup, nullptr, getter_AddRefs(listener), false))) { NS_ERROR("nsXMLDocument::Load: Failed to start the document load."); return rv; } // After this point, if we error out of this method we should clear // mChannelIsPending. // Start an asynchronous read of the XML document rv = channel->AsyncOpen(listener, nullptr); if (NS_FAILED(rv)) { mChannelIsPending = false; return rv; } if (!mAsync) { nsCOMPtr<nsIThread> thread = do_GetCurrentThread(); nsAutoSyncOperation sync(this); mLoopingForSyncLoad = true; while (mLoopingForSyncLoad) { if (!NS_ProcessNextEvent(thread)) break; } // We set return to true unless there was a parsing error nsCOMPtr<nsIDOMNode> node = do_QueryInterface(GetRootElement()); if (node) { nsAutoString name, ns; if (NS_SUCCEEDED(node->GetLocalName(name)) && name.EqualsLiteral("parsererror") && NS_SUCCEEDED(node->GetNamespaceURI(ns)) && ns.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) { //return is already false } else { *aReturn = true; } } } else { *aReturn = true; } return NS_OK; }