NS_IMETHODIMP nsAboutProtocolHandler::NewURI(const nsACString &aSpec, const char *aCharset, // ignore charset info nsIURI *aBaseURI, nsIURI **result) { *result = nullptr; nsresult rv; // Use a simple URI to parse out some stuff first nsCOMPtr<nsIURI> url = do_CreateInstance(kSimpleURICID, &rv); if (NS_FAILED(rv)) return rv; rv = url->SetSpec(aSpec); if (NS_FAILED(rv)) { return rv; } // Unfortunately, people create random about: URIs that don't correspond to // about: modules... Since those URIs will never open a channel, might as // well consider them unsafe for better perf, and just in case. bool isSafe = false; nsCOMPtr<nsIAboutModule> aboutMod; rv = NS_GetAboutModule(url, getter_AddRefs(aboutMod)); if (NS_SUCCEEDED(rv)) { isSafe = IsSafeForUntrustedContent(aboutMod, url); } if (isSafe) { // We need to indicate that this baby is safe. Use an inner URI that // no one but the security manager will see. Make sure to preserve our // path, in case someone decides to hardcode checks for particular // about: URIs somewhere. nsAutoCString spec; rv = url->GetPath(spec); NS_ENSURE_SUCCESS(rv, rv); spec.Insert("moz-safe-about:", 0); nsCOMPtr<nsIURI> inner; rv = NS_NewURI(getter_AddRefs(inner), spec); NS_ENSURE_SUCCESS(rv, rv); nsSimpleNestedURI* outer = new nsNestedAboutURI(inner, aBaseURI); NS_ENSURE_TRUE(outer, NS_ERROR_OUT_OF_MEMORY); // Take a ref to it in the COMPtr we plan to return url = outer; rv = outer->SetSpec(aSpec); NS_ENSURE_SUCCESS(rv, rv); } // We don't want to allow mutation, since it would allow safe and // unsafe URIs to change into each other... NS_TryToSetImmutable(url); url.swap(*result); return NS_OK; }
NS_IMETHODIMP nsAboutProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result) { NS_ENSURE_ARG_POINTER(uri); // about:what you ask? nsCOMPtr<nsIAboutModule> aboutMod; nsresult rv = NS_GetAboutModule(uri, getter_AddRefs(aboutMod)); nsAutoCString path; nsresult rv2 = NS_GetAboutModuleName(uri, path); if (NS_SUCCEEDED(rv2) && path.EqualsLiteral("srcdoc")) { // about:srcdoc is meant to be unresolvable, yet is included in the // about lookup tables so that it can pass security checks when used in // a srcdoc iframe. To ensure that it stays unresolvable, we pretend // that it doesn't exist. rv = NS_ERROR_FACTORY_NOT_REGISTERED; } if (NS_SUCCEEDED(rv)) { // The standard return case: rv = aboutMod->NewChannel(uri, result); if (NS_SUCCEEDED(rv)) { // If this URI is safe for untrusted content, enforce that its // principal be based on the channel's originalURI by setting the // owner to null. // Note: this relies on aboutMod's newChannel implementation // having set the proper originalURI, which probably isn't ideal. if (IsSafeForUntrustedContent(aboutMod, uri)) { (*result)->SetOwner(nullptr); } nsRefPtr<nsNestedAboutURI> aboutURI; nsresult rv2 = uri->QueryInterface(kNestedAboutURICID, getter_AddRefs(aboutURI)); if (NS_SUCCEEDED(rv2) && aboutURI->GetBaseURI()) { nsCOMPtr<nsIWritablePropertyBag2> writableBag = do_QueryInterface(*result); if (writableBag) { writableBag-> SetPropertyAsInterface(NS_LITERAL_STRING("baseURI"), aboutURI->GetBaseURI()); } } } return rv; } // mumble... if (rv == NS_ERROR_FACTORY_NOT_REGISTERED) { // This looks like an about: we don't know about. Convert // this to an invalid URI error. rv = NS_ERROR_MALFORMED_URI; } return rv; }
NS_IMETHODIMP nsAboutProtocolHandler::NewChannel2(nsIURI* uri, nsILoadInfo* aLoadInfo, nsIChannel** result) { NS_ENSURE_ARG_POINTER(uri); // about:what you ask? nsCOMPtr<nsIAboutModule> aboutMod; nsresult rv = NS_GetAboutModule(uri, getter_AddRefs(aboutMod)); nsAutoCString path; nsresult rv2 = NS_GetAboutModuleName(uri, path); if (NS_SUCCEEDED(rv2) && path.EqualsLiteral("srcdoc")) { // about:srcdoc is meant to be unresolvable, yet is included in the // about lookup tables so that it can pass security checks when used in // a srcdoc iframe. To ensure that it stays unresolvable, we pretend // that it doesn't exist. rv = NS_ERROR_FACTORY_NOT_REGISTERED; } if (NS_SUCCEEDED(rv)) { // The standard return case: rv = aboutMod->NewChannel(uri, aLoadInfo, result); if (NS_SUCCEEDED(rv)) { // Not all implementations of nsIAboutModule::NewChannel() // set the LoadInfo on the newly created channel yet, as // an interim solution we set the LoadInfo here if not // available on the channel. Bug 1087720 nsCOMPtr<nsILoadInfo> loadInfo = (*result)->GetLoadInfo(); if (aLoadInfo != loadInfo) { if (loadInfo) { NS_ASSERTION(false, "nsIAboutModule->newChannel(aURI, aLoadInfo) needs to set LoadInfo"); const char16_t* params[] = { u"nsIAboutModule->newChannel(aURI)", u"nsIAboutModule->newChannel(aURI, aLoadInfo)" }; nsContentUtils::ReportToConsole( nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Security by Default"), nullptr, // aDocument nsContentUtils::eNECKO_PROPERTIES, "APIDeprecationWarning", params, mozilla::ArrayLength(params)); } (*result)->SetLoadInfo(aLoadInfo); } // If this URI is safe for untrusted content, enforce that its // principal be based on the channel's originalURI by setting the // owner to null. // Note: this relies on aboutMod's newChannel implementation // having set the proper originalURI, which probably isn't ideal. if (IsSafeForUntrustedContent(aboutMod, uri)) { (*result)->SetOwner(nullptr); } RefPtr<nsNestedAboutURI> aboutURI; nsresult rv2 = uri->QueryInterface(kNestedAboutURICID, getter_AddRefs(aboutURI)); if (NS_SUCCEEDED(rv2) && aboutURI->GetBaseURI()) { nsCOMPtr<nsIWritablePropertyBag2> writableBag = do_QueryInterface(*result); if (writableBag) { writableBag-> SetPropertyAsInterface(NS_LITERAL_STRING("baseURI"), aboutURI->GetBaseURI()); } } } return rv; } // mumble... if (rv == NS_ERROR_FACTORY_NOT_REGISTERED) { // This looks like an about: we don't know about. Convert // this to an invalid URI error. rv = NS_ERROR_MALFORMED_URI; } return rv; }