void nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, PRInt16 aContentDecision) { // Sanity NS_ABORT_IF_FALSE(!NS_CP_ACCEPTED(aContentDecision), "Blocked but not?"); // We do some slightly illogical stuff here to maintain consistency with // old behavior that people probably depend on. Even in the case where the // new image is blocked, the old one should really be canceled with the // reason "image source changed". However, apparently there's some abuse // over in nsImageFrame where the displaying of the "broken" icon for the // next image depends on the cancel reason of the previous image. ugh. ClearPendingRequest(NS_ERROR_IMAGE_BLOCKED); // For the blocked case, we only want to cancel the existing current request // if size is not available. bz says the web depends on this behavior. if (!HaveSize(mCurrentRequest)) { mImageBlockingStatus = aContentDecision; ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED); // We still want to remember what URI we were despite not having an actual // request. mCurrentURI = aURI; } }
void ImportLoader::Open() { AutoError ae(this, false); // Imports should obey to the master documents CSP. nsCOMPtr<nsIDocument> master = mImportParent->MasterDocument(); nsIPrincipal* principal = Principal(); int16_t shouldLoad = nsIContentPolicy::ACCEPT; nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SUBDOCUMENT, mURI, principal, mImportParent, NS_LITERAL_CSTRING("text/html"), /* extra = */ nullptr, &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { NS_WARN_IF_FALSE(NS_CP_ACCEPTED(shouldLoad), "ImportLoader rejected by CSP"); return; } nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); rv = secMan->CheckLoadURIWithPrincipal(principal, mURI, nsIScriptSecurityManager::STANDARD); NS_ENSURE_SUCCESS_VOID(rv); nsCOMPtr<nsILoadGroup> loadGroup = master->GetDocumentLoadGroup(); nsCOMPtr<nsIChannel> channel; rv = NS_NewChannel(getter_AddRefs(channel), mURI, mImportParent, nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_SUBDOCUMENT, loadGroup, nullptr, // aCallbacks nsIRequest::LOAD_BACKGROUND); NS_ENSURE_SUCCESS_VOID(rv); // Init CORSListenerProxy and omit credentials. nsRefPtr<nsCORSListenerProxy> corsListener = new nsCORSListenerProxy(this, principal, /* aWithCredentials */ false); rv = corsListener->Init(channel, true); NS_ENSURE_SUCCESS_VOID(rv); rv = channel->AsyncOpen(corsListener, nullptr); NS_ENSURE_SUCCESS_VOID(rv); BlockScripts(); ae.Pass(); }
nsresult nsImageLoadingContent::LoadImage(nsIURI* aNewURI, PRBool aForce, PRBool aNotify, nsIDocument* aDocument, nsLoadFlags aLoadFlags) { if (!mLoadingEnabled) { // XXX Why fire an error here? seems like the callers to SetLoadingEnabled // don't want/need it. FireEvent(NS_LITERAL_STRING("error")); return NS_OK; } NS_ASSERTION(!aDocument || aDocument == GetOurDocument(), "Bogus document passed in"); // First, get a document (needed for security checks and the like) if (!aDocument) { aDocument = GetOurDocument(); if (!aDocument) { // No reason to bother, I think... return NS_OK; } } // URI equality check. // // We skip the equality check if our current image was blocked, since in that // case we really do want to try loading again. if (!aForce && NS_CP_ACCEPTED(mImageBlockingStatus)) { nsCOMPtr<nsIURI> currentURI; GetCurrentURI(getter_AddRefs(currentURI)); PRBool equal; if (currentURI && NS_SUCCEEDED(currentURI->Equals(aNewURI, &equal)) && equal) { // Nothing to do here. return NS_OK; } } // From this point on, our image state could change. Watch it. AutoStateChanger changer(this, aNotify); // Sanity check. // // We use the principal of aDocument to avoid having to QI |this| an extra // time. It should always be the same as the principal of this node. #ifdef DEBUG nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this); NS_ABORT_IF_FALSE(thisContent && thisContent->NodePrincipal() == aDocument->NodePrincipal(), "Principal mismatch?"); #endif // Are we blocked? PRInt16 cpDecision = nsIContentPolicy::REJECT_REQUEST; nsContentUtils::CanLoadImage(aNewURI, this, aDocument, aDocument->NodePrincipal(), &cpDecision); if (!NS_CP_ACCEPTED(cpDecision)) { FireEvent(NS_LITERAL_STRING("error")); SetBlockedRequest(aNewURI, cpDecision); return NS_OK; } // Not blocked. Do the load. nsCOMPtr<imgIRequest>& req = PrepareNextRequest(); nsresult rv; rv = nsContentUtils::LoadImage(aNewURI, aDocument, aDocument->NodePrincipal(), aDocument->GetDocumentURI(), this, aLoadFlags, getter_AddRefs(req)); if (NS_SUCCEEDED(rv)) { TrackImage(req); } else { // If we don't have a current URI, we might as well store this URI so people // know what we tried (and failed) to load. if (!mCurrentRequest) mCurrentURI = aNewURI; FireEvent(NS_LITERAL_STRING("error")); return NS_OK; } return NS_OK; }