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 nsAboutRedirector::NewChannel(nsIURI *aURI, nsIChannel **result) { NS_ENSURE_ARG_POINTER(aURI); NS_ASSERTION(result, "must not be null"); nsresult rv; nsCAutoString path; rv = NS_GetAboutModuleName(aURI, path); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); if (NS_FAILED(rv)) return rv; for (int i=0; i<kRedirTotal; i++) { if (!strcmp(path.get(), kRedirMap[i].id)) { nsCOMPtr<nsIChannel> tempChannel; rv = ioService->NewChannel(nsDependentCString(kRedirMap[i].url), nsnull, nsnull, getter_AddRefs(tempChannel)); if (NS_FAILED(rv)) return rv; tempChannel->SetOriginalURI(aURI); // Keep the page from getting unnecessary privileges unless it needs them if (kRedirMap[i].flags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT) { nsCOMPtr<nsIScriptSecurityManager> securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIPrincipal> principal; rv = securityManager->GetCodebasePrincipal(aURI, getter_AddRefs(principal)); if (NS_FAILED(rv)) return rv; rv = tempChannel->SetOwner(principal); if (NS_FAILED(rv)) return rv; } NS_ADDREF(*result = tempChannel); return rv; } } NS_ERROR("nsAboutRedirector called for unknown case"); return NS_ERROR_ILLEGAL_VALUE; }
NS_IMETHODIMP nsAboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** aResult) { NS_ENSURE_ARG_POINTER(aURI); NS_ASSERTION(aResult, "must not be null"); nsAutoCString path; nsresult rv = NS_GetAboutModuleName(aURI, path); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); NS_ENSURE_SUCCESS(rv, rv); for (int i = 0; i < kRedirTotal; i++) { if (!strcmp(path.get(), kRedirMap[i].id)) { nsCOMPtr<nsIChannel> tempChannel; nsCOMPtr<nsIURI> tempURI; rv = NS_NewURI(getter_AddRefs(tempURI), kRedirMap[i].url); NS_ENSURE_SUCCESS(rv, rv); // If tempURI links to an external URI (i.e. something other than // chrome:// or resource://) then set the LOAD_REPLACE flag on the // channel which forces the channel owner to reflect the displayed // URL rather then being the systemPrincipal. bool isUIResource = false; rv = NS_URIChainHasFlags(tempURI, nsIProtocolHandler::URI_IS_UI_RESOURCE, &isUIResource); NS_ENSURE_SUCCESS(rv, rv); bool isAboutBlank = NS_IsAboutBlank(tempURI); nsLoadFlags loadFlags = isUIResource || isAboutBlank ? static_cast<nsLoadFlags>(nsIChannel::LOAD_NORMAL) : static_cast<nsLoadFlags>(nsIChannel::LOAD_REPLACE); rv = NS_NewChannelInternal(getter_AddRefs(tempChannel), tempURI, aLoadInfo, nullptr, // aLoadGroup nullptr, // aCallbacks loadFlags); NS_ENSURE_SUCCESS(rv, rv); tempChannel->SetOriginalURI(aURI); tempChannel.forget(aResult); return rv; } } NS_ERROR("nsAboutRedirector called for unknown case"); return NS_ERROR_ILLEGAL_VALUE; }
NS_IMETHODIMP nsAboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** result) { NS_ENSURE_ARG_POINTER(aURI); NS_ASSERTION(result, "must not be null"); nsAutoCString path; nsresult rv = NS_GetAboutModuleName(aURI, path); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); NS_ENSURE_SUCCESS(rv, rv); for (int i=0; i<kRedirTotal; i++) { if (!strcmp(path.get(), kRedirMap[i].id)) { nsCOMPtr<nsIChannel> tempChannel; nsCOMPtr<nsIURI> tempURI; rv = NS_NewURI(getter_AddRefs(tempURI), kRedirMap[i].url); NS_ENSURE_SUCCESS(rv, rv); // Bug 1087720 (and Bug 1099296): // Once all callsites have been updated to call NewChannel2() // instead of NewChannel() we should have a non-null loadInfo // consistently. Until then we have to branch on the loadInfo. if (aLoadInfo) { rv = NS_NewChannelInternal(getter_AddRefs(tempChannel), tempURI, aLoadInfo); } else { rv = ioService->NewChannelFromURI(tempURI, getter_AddRefs(tempChannel)); } if (NS_FAILED(rv)) return rv; tempChannel->SetOriginalURI(aURI); NS_ADDREF(*result = tempChannel); return rv; } } NS_ERROR("nsAboutRedirector called for unknown case"); return NS_ERROR_ILLEGAL_VALUE; }
NS_IMETHODIMP nsAboutRedirector::NewChannel(nsIURI *aURI, nsIChannel **result) { NS_ENSURE_ARG_POINTER(aURI); NS_ASSERTION(result, "must not be null"); nsresult rv; nsAutoCString path; rv = NS_GetAboutModuleName(aURI, path); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); if (NS_FAILED(rv)) return rv; for (int i=0; i<kRedirTotal; i++) { if (!strcmp(path.get(), kRedirMap[i].id)) { nsCOMPtr<nsIChannel> tempChannel; rv = ioService->NewChannel(nsDependentCString(kRedirMap[i].url), nullptr, nullptr, getter_AddRefs(tempChannel)); if (NS_FAILED(rv)) return rv; tempChannel->SetOriginalURI(aURI); // Keep the page from getting unnecessary privileges unless it needs them if (kRedirMap[i].flags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT) { // Setting the owner to null means that we'll go through the normal // path in GetChannelPrincipal and create a codebase principal based // on the channel's originalURI rv = tempChannel->SetOwner(nullptr); if (NS_FAILED(rv)) return rv; } NS_ADDREF(*result = tempChannel); return rv; } } NS_ERROR("nsAboutRedirector called for unknown case"); return NS_ERROR_ILLEGAL_VALUE; }
NS_IMETHODIMP nsAboutRedirector::GetURIFlags(nsIURI* aURI, uint32_t* aResult) { NS_ENSURE_ARG_POINTER(aURI); nsAutoCString name; nsresult rv = NS_GetAboutModuleName(aURI, name); NS_ENSURE_SUCCESS(rv, rv); for (int i = 0; i < kRedirTotal; i++) { if (name.EqualsASCII(kRedirMap[i].id)) { *aResult = kRedirMap[i].flags; return NS_OK; } } NS_ERROR("nsAboutRedirector called for unknown case"); return NS_ERROR_ILLEGAL_VALUE; }
NS_IMETHODIMP nsAboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** aResult) { NS_ENSURE_ARG_POINTER(aURI); NS_ASSERTION(aResult, "must not be null"); nsAutoCString path; nsresult rv = NS_GetAboutModuleName(aURI, path); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); NS_ENSURE_SUCCESS(rv, rv); for (int i = 0; i < kRedirTotal; i++) { if (!strcmp(path.get(), kRedirMap[i].id)) { nsCOMPtr<nsIChannel> tempChannel; nsCOMPtr<nsIURI> tempURI; rv = NS_NewURI(getter_AddRefs(tempURI), kRedirMap[i].url); NS_ENSURE_SUCCESS(rv, rv); rv = NS_NewChannelInternal(getter_AddRefs(tempChannel), tempURI, aLoadInfo); if (NS_FAILED(rv)) { return rv; } tempChannel->SetOriginalURI(aURI); tempChannel.forget(aResult); return rv; } } NS_ERROR("nsAboutRedirector called for unknown case"); return NS_ERROR_ILLEGAL_VALUE; }
NS_IMETHODIMP nsAboutRedirector::NewChannel(nsIURI *aURI, nsIChannel **result) { NS_ENSURE_ARG_POINTER(aURI); NS_ASSERTION(result, "must not be null"); nsresult rv; nsAutoCString path; rv = NS_GetAboutModuleName(aURI, path); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); if (NS_FAILED(rv)) return rv; for (int i=0; i<kRedirTotal; i++) { if (!strcmp(path.get(), kRedirMap[i].id)) { nsCOMPtr<nsIChannel> tempChannel; rv = ioService->NewChannel(nsDependentCString(kRedirMap[i].url), nullptr, nullptr, getter_AddRefs(tempChannel)); if (NS_FAILED(rv)) return rv; tempChannel->SetOriginalURI(aURI); NS_ADDREF(*result = tempChannel); return rv; } } NS_ERROR("nsAboutRedirector called for unknown case"); return NS_ERROR_ILLEGAL_VALUE; }
NS_IMETHODIMP nsAboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** aResult) { NS_ENSURE_ARG_POINTER(aURI); NS_ENSURE_ARG_POINTER(aLoadInfo); NS_ASSERTION(aResult, "must not be null"); nsAutoCString path; nsresult rv = NS_GetAboutModuleName(aURI, path); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); NS_ENSURE_SUCCESS(rv, rv); if (path.EqualsASCII("crashparent") || path.EqualsASCII("crashcontent")) { nsCOMPtr<nsIChannel> channel = new CrashChannel(aURI); channel.forget(aResult); return NS_OK; } #ifdef ABOUT_CONFIG_BLOCKED_GV // We don't want to allow access to about:config from // GeckoView on release or beta, but it's fine for Fennec. if (path.EqualsASCII("config") && !mozilla::jni::IsFennec()) { return NS_ERROR_NOT_AVAILABLE; } #endif for (int i = 0; i < kRedirTotal; i++) { if (!strcmp(path.get(), kRedirMap[i].id)) { nsCOMPtr<nsIChannel> tempChannel; nsCOMPtr<nsIURI> tempURI; rv = NS_NewURI(getter_AddRefs(tempURI), kRedirMap[i].url); NS_ENSURE_SUCCESS(rv, rv); rv = NS_NewChannelInternal(getter_AddRefs(tempChannel), tempURI, aLoadInfo); NS_ENSURE_SUCCESS(rv, rv); // If tempURI links to an external URI (i.e. something other than // chrome:// or resource://) then set result principal URI on the // load info which forces the channel principal to reflect the displayed // URL rather then being the systemPrincipal. bool isUIResource = false; rv = NS_URIChainHasFlags(tempURI, nsIProtocolHandler::URI_IS_UI_RESOURCE, &isUIResource); NS_ENSURE_SUCCESS(rv, rv); bool isAboutBlank = NS_IsAboutBlank(tempURI); if (!isUIResource && !isAboutBlank) { aLoadInfo->SetResultPrincipalURI(tempURI); } tempChannel->SetOriginalURI(aURI); tempChannel.forget(aResult); return rv; } } NS_ERROR("nsAboutRedirector called for unknown case"); return NS_ERROR_ILLEGAL_VALUE; }
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; }