void URL::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv) { nsAString::const_iterator start, end; aProtocol.BeginReading(start); aProtocol.EndReading(end); nsAString::const_iterator iter(start); FindCharInReadable(':', iter, end); // Changing the protocol of a URL, changes the "nature" of the URI // implementation. In order to do this properly, we have to serialize the // existing URL and reparse it in a new object. nsCOMPtr<nsIURI> clone; nsresult rv = mURI->Clone(getter_AddRefs(clone)); if (NS_WARN_IF(NS_FAILED(rv)) || !clone) { return; } rv = clone->SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter))); if (NS_WARN_IF(NS_FAILED(rv))) { return; } nsAutoCString href; rv = clone->GetSpec(href); if (NS_WARN_IF(NS_FAILED(rv))) { return; } nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), href); if (NS_WARN_IF(NS_FAILED(rv))) { return; } mURI = uri; }
nsresult Link::SetHost(const nsAString &aHost) { nsCOMPtr<nsIURI> uri(GetURIToMutate()); if (!uri) { // Ignore failures to be compatible with NS4. return NS_OK; } // We cannot simply call nsIURI::SetHost because that would treat the name as // an IPv6 address (like http:://[server:443]/). We also cannot call // nsIURI::SetHostPort because that isn't implemented. Sadfaces. // First set the hostname. nsAString::const_iterator start, end; aHost.BeginReading(start); aHost.EndReading(end); nsAString::const_iterator iter(start); (void)FindCharInReadable(':', iter, end); NS_ConvertUTF16toUTF8 host(Substring(start, iter)); (void)uri->SetHost(host); // Also set the port if needed. if (iter != end) { iter++; if (iter != end) { nsAutoString portStr(Substring(iter, end)); nsresult rv; int32_t port = portStr.ToInteger(&rv); if (NS_SUCCEEDED(rv)) { (void)uri->SetPort(port); } } }; SetHrefAttribute(uri); return NS_OK; }
nsresult ClientIDFromCacheKey(const nsACString& key, char ** result) { nsresult rv = NS_OK; *result = nullptr; nsReadingIterator<char> colon; key.BeginReading(colon); nsReadingIterator<char> start; key.BeginReading(start); nsReadingIterator<char> end; key.EndReading(end); if (FindCharInReadable(':', colon, end)) { *result = ToNewCString( Substring(start, colon)); if (!*result) rv = NS_ERROR_OUT_OF_MEMORY; } else { NS_ASSERTION(false, "FindCharInRead failed to find ':'"); rv = NS_ERROR_UNEXPECTED; } return rv; }
/*static*/ already_AddRefed<Response> Response::Constructor(const GlobalObject& aGlobal, const Optional<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>& aBody, const ResponseInit& aInit, ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); if (aInit.mStatus < 200 || aInit.mStatus > 599) { aRv.ThrowRangeError(MSG_INVALID_RESPONSE_STATUSCODE_ERROR); return nullptr; } nsCString statusText; if (aInit.mStatusText.WasPassed()) { statusText = aInit.mStatusText.Value(); nsACString::const_iterator start, end; statusText.BeginReading(start); statusText.EndReading(end); if (FindCharInReadable('\r', start, end)) { aRv.ThrowTypeError(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR); return nullptr; } // Reset iterator since FindCharInReadable advances it. statusText.BeginReading(start); if (FindCharInReadable('\n', start, end)) { aRv.ThrowTypeError(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR); return nullptr; } } else { // Since we don't support default values for ByteString. statusText = NS_LITERAL_CSTRING("OK"); } nsRefPtr<InternalResponse> internalResponse = new InternalResponse(aInit.mStatus, statusText); nsRefPtr<Response> r = new Response(global, internalResponse); if (aInit.mHeaders.WasPassed()) { internalResponse->Headers()->Clear(); // Instead of using Fill, create an object to allow the constructor to // unwrap the HeadersInit. nsRefPtr<Headers> headers = Headers::Create(global, aInit.mHeaders.Value(), aRv); if (aRv.Failed()) { return nullptr; } internalResponse->Headers()->Fill(*headers->GetInternalHeaders(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } if (aBody.WasPassed()) { nsCOMPtr<nsIInputStream> bodyStream; nsCString contentType; aRv = ExtractByteStreamFromBody(aBody.Value(), getter_AddRefs(bodyStream), contentType); internalResponse->SetBody(bodyStream); if (!contentType.IsVoid() && !internalResponse->Headers()->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) { internalResponse->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, aRv); } if (aRv.Failed()) { return nullptr; } } r->SetMimeType(); return r.forget(); }
bool ParseHeader(nsACString::const_iterator& aStart, nsACString::const_iterator& aEnd, bool* aWasEmptyHeader) { MOZ_ASSERT(aWasEmptyHeader); // Set it to a valid value here so we don't forget later. *aWasEmptyHeader = false; const char* beginning = aStart.get(); nsACString::const_iterator end(aEnd); if (!FindCRLF(aStart, end)) { return false; } if (aStart.get() == beginning) { *aWasEmptyHeader = true; return true; } nsAutoCString header(beginning, aStart.get() - beginning); nsACString::const_iterator headerStart, headerEnd; header.BeginReading(headerStart); header.EndReading(headerEnd); if (!FindCharInReadable(':', headerStart, headerEnd)) { return false; } nsAutoCString headerName(StringHead(header, headerStart.size_backward())); headerName.CompressWhitespace(); if (!NS_IsValidHTTPToken(headerName)) { return false; } nsAutoCString headerValue(Substring(++headerStart, headerEnd)); if (!NS_IsReasonableHTTPHeaderValue(headerValue)) { return false; } headerValue.CompressWhitespace(); if (headerName.LowerCaseEqualsLiteral("content-disposition")) { nsCCharSeparatedTokenizer tokenizer(headerValue, ';'); bool seenFormData = false; while (tokenizer.hasMoreTokens()) { const nsDependentCSubstring& token = tokenizer.nextToken(); if (token.IsEmpty()) { continue; } if (token.EqualsLiteral("form-data")) { seenFormData = true; continue; } if (seenFormData && StringBeginsWith(token, NS_LITERAL_CSTRING("name="))) { mName = StringTail(token, token.Length() - 5); mName.Trim(" \""); continue; } if (seenFormData && StringBeginsWith(token, NS_LITERAL_CSTRING("filename="))) { mFilename = StringTail(token, token.Length() - 9); mFilename.Trim(" \""); continue; } } if (mName.IsVoid()) { // Could not parse a valid entry name. return false; } } else if (headerName.LowerCaseEqualsLiteral("content-type")) { mContentType = headerValue; } return true; }
/** * Reads the MAC from the response and checks it against the * locally-computed MAC. */ nsresult nsUrlClassifierHashCompleterRequest::HandleMAC(nsACString::const_iterator& begin, const nsACString::const_iterator& end) { mVerified = PR_FALSE; // First line should be either the MAC or a k:pleaserekey request. nsACString::const_iterator iter = begin; if (!FindCharInReadable('\n', iter, end)) { return NS_ERROR_FAILURE; } nsCAutoString serverMAC(Substring(begin, iter++)); begin = iter; if (serverMAC.EqualsLiteral("e:pleaserekey")) { LOG(("Rekey requested")); // Reschedule our items to be requested again. RescheduleItems(); // Let the hash completer know that we need a new key. return mCompleter->RekeyRequested(); } nsUrlClassifierUtils::UnUrlsafeBase64(serverMAC); nsresult rv; nsCOMPtr<nsIKeyObjectFactory> keyObjectFactory( do_GetService("@mozilla.org/security/keyobjectfactory;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIKeyObject> keyObject; rv = keyObjectFactory->KeyFromString(nsIKeyObject::HMAC, mClientKey, getter_AddRefs(keyObject)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsICryptoHMAC> hmac = do_CreateInstance(NS_CRYPTO_HMAC_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = hmac->Init(nsICryptoHMAC::SHA1, keyObject); NS_ENSURE_SUCCESS(rv, rv); const nsCSubstring &remaining = Substring(begin, end); rv = hmac->Update(reinterpret_cast<const PRUint8*>(remaining.BeginReading()), remaining.Length()); NS_ENSURE_SUCCESS(rv, rv); nsCAutoString clientMAC; rv = hmac->Finish(PR_TRUE, clientMAC); NS_ENSURE_SUCCESS(rv, rv); if (clientMAC != serverMAC) { NS_WARNING("Invalid MAC in gethash response."); return NS_ERROR_FAILURE; } mVerified = PR_TRUE; return NS_OK; }
/*static*/ already_AddRefed<Response> Response::Constructor(const GlobalObject& aGlobal, const Optional<Nullable<fetch::ResponseBodyInit>>& aBody, const ResponseInit& aInit, ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); if (aInit.mStatus < 200 || aInit.mStatus > 599) { aRv.ThrowRangeError<MSG_INVALID_RESPONSE_STATUSCODE_ERROR>(); return nullptr; } // Check if the status text contains illegal characters nsACString::const_iterator start, end; aInit.mStatusText.BeginReading(start); aInit.mStatusText.EndReading(end); if (FindCharInReadable('\r', start, end)) { aRv.ThrowTypeError<MSG_RESPONSE_INVALID_STATUSTEXT_ERROR>(); return nullptr; } // Reset iterator since FindCharInReadable advances it. aInit.mStatusText.BeginReading(start); if (FindCharInReadable('\n', start, end)) { aRv.ThrowTypeError<MSG_RESPONSE_INVALID_STATUSTEXT_ERROR>(); return nullptr; } RefPtr<InternalResponse> internalResponse = new InternalResponse(aInit.mStatus, aInit.mStatusText); // Grab a valid channel info from the global so this response is 'valid' for // interception. if (NS_IsMainThread()) { ChannelInfo info; nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global); if (window) { nsIDocument* doc = window->GetExtantDoc(); MOZ_ASSERT(doc); info.InitFromDocument(doc); } else { info.InitFromChromeGlobal(global); } internalResponse->InitChannelInfo(info); } else { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); internalResponse->InitChannelInfo(worker->GetChannelInfo()); } RefPtr<Response> r = new Response(global, internalResponse, nullptr); if (aInit.mHeaders.WasPassed()) { internalResponse->Headers()->Clear(); // Instead of using Fill, create an object to allow the constructor to // unwrap the HeadersInit. RefPtr<Headers> headers = Headers::Create(global, aInit.mHeaders.Value(), aRv); if (aRv.Failed()) { return nullptr; } internalResponse->Headers()->Fill(*headers->GetInternalHeaders(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } if (aBody.WasPassed() && !aBody.Value().IsNull()) { if (aInit.mStatus == 204 || aInit.mStatus == 205 || aInit.mStatus == 304) { aRv.ThrowTypeError<MSG_RESPONSE_NULL_STATUS_WITH_BODY>(); return nullptr; } nsCString contentTypeWithCharset; nsCOMPtr<nsIInputStream> bodyStream; int64_t bodySize = InternalResponse::UNKNOWN_BODY_SIZE; const fetch::ResponseBodyInit& body = aBody.Value().Value(); if (body.IsReadableStream()) { aRv.MightThrowJSException(); JSContext* cx = aGlobal.Context(); const ReadableStream& readableStream = body.GetAsReadableStream(); JS::Rooted<JSObject*> readableStreamObj(cx, readableStream.Obj()); bool disturbed; bool locked; if (!JS::ReadableStreamIsDisturbed(cx, readableStreamObj, &disturbed) || !JS::ReadableStreamIsLocked(cx, readableStreamObj, &locked)) { aRv.StealExceptionFromJSContext(cx); return nullptr; } if (disturbed || locked) { aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>(); return nullptr; } r->SetReadableStreamBody(cx, readableStreamObj); JS::ReadableStreamMode streamMode; if (!JS::ReadableStreamGetMode(cx, readableStreamObj, &streamMode)) { aRv.StealExceptionFromJSContext(cx); return nullptr; } if (streamMode == JS::ReadableStreamMode::ExternalSource) { // If this is a DOM generated ReadableStream, we can extract the // inputStream directly. void* underlyingSource = nullptr; if (!JS::ReadableStreamGetExternalUnderlyingSource(cx, readableStreamObj, &underlyingSource)) { aRv.StealExceptionFromJSContext(cx); return nullptr; } MOZ_ASSERT(underlyingSource); aRv = FetchStream::RetrieveInputStream(underlyingSource, getter_AddRefs(bodyStream)); // The releasing of the external source is needed in order to avoid an // extra stream lock. if (!JS::ReadableStreamReleaseExternalUnderlyingSource(cx, readableStreamObj)) { aRv.StealExceptionFromJSContext(cx); return nullptr; } if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } else { // If this is a JS-created ReadableStream, let's create a // FetchStreamReader. aRv = FetchStreamReader::Create(aGlobal.Context(), global, getter_AddRefs(r->mFetchStreamReader), getter_AddRefs(bodyStream)); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } } else { uint64_t size = 0; aRv = ExtractByteStreamFromBody(body, getter_AddRefs(bodyStream), contentTypeWithCharset, size); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } bodySize = size; } internalResponse->SetBody(bodyStream, bodySize); if (!contentTypeWithCharset.IsVoid() && !internalResponse->Headers()->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) { // Ignore Append() failing here. ErrorResult error; internalResponse->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentTypeWithCharset, error); error.SuppressException(); } if (aRv.Failed()) { return nullptr; } } r->SetMimeType(); return r.forget(); }
void nsUrlClassifierUtils::ParseIPAddress(const nsACString & host, nsACString & _retval) { _retval.Truncate(); nsACString::const_iterator iter, end; host.BeginReading(iter); host.EndReading(end); if (host.Length() <= 15) { // The Windows resolver allows a 4-part dotted decimal IP address to // have a space followed by any old rubbish, so long as the total length // of the string doesn't get above 15 characters. So, "10.192.95.89 xy" // is resolved to 10.192.95.89. // If the string length is greater than 15 characters, e.g. // "10.192.95.89 xy.wildcard.example.com", it will be resolved through // DNS. if (FindCharInReadable(' ', iter, end)) { end = iter; } } for (host.BeginReading(iter); iter != end; iter++) { if (!(isxdigit(*iter) || *iter == 'x' || *iter == 'X' || *iter == '.')) { // not an IP return; } } host.BeginReading(iter); nsTArray<nsCString> parts; ParseString(PromiseFlatCString(Substring(iter, end)), '.', parts); if (parts.Length() > 4) { return; } // If any potentially-octal numbers (start with 0 but not hex) have // non-octal digits, no part of the ip can be in octal // XXX: this came from the old javascript implementation, is it really // supposed to be like this? bool allowOctal = true; uint32_t i; for (i = 0; i < parts.Length(); i++) { const nsCString& part = parts[i]; if (part[0] == '0') { for (uint32_t j = 1; j < part.Length(); j++) { if (part[j] == 'x') { break; } if (part[j] == '8' || part[j] == '9') { allowOctal = false; break; } } } } for (i = 0; i < parts.Length(); i++) { nsAutoCString canonical; if (i == parts.Length() - 1) { CanonicalNum(parts[i], 5 - parts.Length(), allowOctal, canonical); } else { CanonicalNum(parts[i], 1, allowOctal, canonical); } if (canonical.IsEmpty()) { _retval.Truncate(); return; } if (_retval.IsEmpty()) { _retval.Assign(canonical); } else { _retval.Append('.'); _retval.Append(canonical); } } return; }
/* static */ nsresult LookupCache::GetLookupFragments(const nsACString& aSpec, nsTArray<nsCString>* aFragments) { aFragments->Clear(); nsACString::const_iterator begin, end, iter; aSpec.BeginReading(begin); aSpec.EndReading(end); iter = begin; if (!FindCharInReadable('/', iter, end)) { return NS_OK; } const nsCSubstring& host = Substring(begin, iter++); nsAutoCString path; path.Assign(Substring(iter, end)); /** * From the protocol doc: * For the hostname, the client will try at most 5 different strings. They * are: * a) The exact hostname of the url * b) The 4 hostnames formed by starting with the last 5 components and * successivly removing the leading component. The top-level component * can be skipped. This is not done if the hostname is a numerical IP. */ nsTArray<nsCString> hosts; hosts.AppendElement(host); if (!IsCanonicalizedIP(host)) { host.BeginReading(begin); host.EndReading(end); int numHostComponents = 0; while (RFindInReadable(NS_LITERAL_CSTRING("."), begin, end) && numHostComponents < MAX_HOST_COMPONENTS) { // don't bother checking toplevel domains if (++numHostComponents >= 2) { host.EndReading(iter); hosts.AppendElement(Substring(end, iter)); } end = begin; host.BeginReading(begin); } } /** * From the protocol doc: * For the path, the client will also try at most 6 different strings. * They are: * a) the exact path of the url, including query parameters * b) the exact path of the url, without query parameters * c) the 4 paths formed by starting at the root (/) and * successively appending path components, including a trailing * slash. This behavior should only extend up to the next-to-last * path component, that is, a trailing slash should never be * appended that was not present in the original url. */ nsTArray<nsCString> paths; nsAutoCString pathToAdd; path.BeginReading(begin); path.EndReading(end); iter = begin; if (FindCharInReadable('?', iter, end)) { pathToAdd = Substring(begin, iter); paths.AppendElement(pathToAdd); end = iter; } int numPathComponents = 1; iter = begin; while (FindCharInReadable('/', iter, end) && numPathComponents < MAX_PATH_COMPONENTS) { iter++; pathToAdd.Assign(Substring(begin, iter)); paths.AppendElement(pathToAdd); numPathComponents++; } // If we haven't already done so, add the full path if (!pathToAdd.Equals(path)) { paths.AppendElement(path); } // Check an empty path (for whole-domain blacklist entries) paths.AppendElement(EmptyCString()); for (uint32_t hostIndex = 0; hostIndex < hosts.Length(); hostIndex++) { for (uint32_t pathIndex = 0; pathIndex < paths.Length(); pathIndex++) { nsCString key; key.Assign(hosts[hostIndex]); key.Append('/'); key.Append(paths[pathIndex]); LOG(("Checking fragment %s", key.get())); aFragments->AppendElement(key); } } return NS_OK; }
/*static*/ already_AddRefed<Response> Response::Constructor(const GlobalObject& aGlobal, const Optional<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>& aBody, const ResponseInit& aInit, ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); if (aInit.mStatus < 200 || aInit.mStatus > 599) { aRv.ThrowRangeError<MSG_INVALID_RESPONSE_STATUSCODE_ERROR>(); return nullptr; } nsCString statusText; if (aInit.mStatusText.WasPassed()) { statusText = aInit.mStatusText.Value(); nsACString::const_iterator start, end; statusText.BeginReading(start); statusText.EndReading(end); if (FindCharInReadable('\r', start, end)) { aRv.ThrowTypeError<MSG_RESPONSE_INVALID_STATUSTEXT_ERROR>(); return nullptr; } // Reset iterator since FindCharInReadable advances it. statusText.BeginReading(start); if (FindCharInReadable('\n', start, end)) { aRv.ThrowTypeError<MSG_RESPONSE_INVALID_STATUSTEXT_ERROR>(); return nullptr; } } else { // Since we don't support default values for ByteString. statusText = NS_LITERAL_CSTRING("OK"); } nsRefPtr<InternalResponse> internalResponse = new InternalResponse(aInit.mStatus, statusText); // Grab a valid channel info from the global so this response is 'valid' for // interception. if (NS_IsMainThread()) { ChannelInfo info; nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(global); if (window) { nsIDocument* doc = window->GetExtantDoc(); MOZ_ASSERT(doc); info.InitFromDocument(doc); } else { info.InitFromChromeGlobal(global); } internalResponse->InitChannelInfo(info); } else { workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); internalResponse->InitChannelInfo(worker->GetChannelInfo()); } nsRefPtr<Response> r = new Response(global, internalResponse); if (aInit.mHeaders.WasPassed()) { internalResponse->Headers()->Clear(); // Instead of using Fill, create an object to allow the constructor to // unwrap the HeadersInit. nsRefPtr<Headers> headers = Headers::Create(global, aInit.mHeaders.Value(), aRv); if (aRv.Failed()) { return nullptr; } internalResponse->Headers()->Fill(*headers->GetInternalHeaders(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } if (aBody.WasPassed()) { if (aInit.mStatus == 204 || aInit.mStatus == 205 || aInit.mStatus == 304) { aRv.ThrowTypeError<MSG_RESPONSE_NULL_STATUS_WITH_BODY>(); return nullptr; } nsCOMPtr<nsIInputStream> bodyStream; nsCString contentType; aRv = ExtractByteStreamFromBody(aBody.Value(), getter_AddRefs(bodyStream), contentType); internalResponse->SetBody(bodyStream); if (!contentType.IsVoid() && !internalResponse->Headers()->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) { internalResponse->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, aRv); } if (aRv.Failed()) { return nullptr; } } r->SetMimeType(); return r.forget(); }
void Location::SetProtocol(const nsAString& aProtocol, nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) { if (!CallerSubsumes(&aSubjectPrincipal)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } nsCOMPtr<nsIURI> uri; aRv = GetURI(getter_AddRefs(uri)); if (NS_WARN_IF(aRv.Failed()) || !uri) { return; } nsAString::const_iterator start, end; aProtocol.BeginReading(start); aProtocol.EndReading(end); nsAString::const_iterator iter(start); Unused << FindCharInReadable(':', iter, end); nsresult rv = NS_MutateURI(uri) .SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter))) .Finalize(uri); if (NS_WARN_IF(NS_FAILED(rv))) { // Oh, I wish nsStandardURL returned NS_ERROR_MALFORMED_URI for _all_ the // malformed cases, not just some of them! aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); return; } nsAutoCString newSpec; aRv = uri->GetSpec(newSpec); if (NS_WARN_IF(aRv.Failed())) { return; } // We may want a new URI class for the new URI, so recreate it: rv = NS_NewURI(getter_AddRefs(uri), newSpec); if (NS_FAILED(rv)) { if (rv == NS_ERROR_MALFORMED_URI) { rv = NS_ERROR_DOM_SYNTAX_ERR; } aRv.Throw(rv); return; } bool isHttp; aRv = uri->SchemeIs("http", &isHttp); if (NS_WARN_IF(aRv.Failed())) { return; } bool isHttps; aRv = uri->SchemeIs("https", &isHttps); if (NS_WARN_IF(aRv.Failed())) { return; } if (!isHttp && !isHttps) { // No-op, per spec. return; } aRv = SetURI(uri); }
NS_IMETHODIMP nsPrefBranch::GetComplexValue(const char *aPrefName, const nsIID & aType, void * *_retval) { nsresult rv; nsXPIDLCString utf8String; // we have to do this one first because it's different than all the rest if (aType.Equals(NS_GET_IID(nsIPrefLocalizedString))) { nsCOMPtr<nsIPrefLocalizedString> theString(do_CreateInstance(NS_PREFLOCALIZEDSTRING_CONTRACTID, &rv)); if (NS_SUCCEEDED(rv)) { const char *pref; PRBool bNeedDefault = PR_FALSE; rv = getValidatedPrefName(aPrefName, &pref); if (NS_FAILED(rv)) return rv; if (mIsDefault) { bNeedDefault = PR_TRUE; } else { // if there is no user (or locked) value if (!PREF_HasUserPref(pref) && !PREF_PrefIsLocked(pref)) { bNeedDefault = PR_TRUE; } } // if we need to fetch the default value, do that instead, otherwise use the // value we pulled in at the top of this function if (bNeedDefault) { nsXPIDLString utf16String; rv = GetDefaultFromPropertiesFile(pref, getter_Copies(utf16String)); if (NS_SUCCEEDED(rv)) { rv = theString->SetData(utf16String.get()); } } else { rv = GetCharPref(aPrefName, getter_Copies(utf8String)); if (NS_SUCCEEDED(rv)) { rv = theString->SetData(NS_ConvertUTF8toUCS2(utf8String).get()); } } if (NS_SUCCEEDED(rv)) { nsIPrefLocalizedString *temp = theString; NS_ADDREF(temp); *_retval = (void *)temp; } } return rv; } // if we can't get the pref, there's no point in being here rv = GetCharPref(aPrefName, getter_Copies(utf8String)); if (NS_FAILED(rv)) { return rv; } if (aType.Equals(NS_GET_IID(nsILocalFile))) { nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv)); if (NS_SUCCEEDED(rv)) { rv = file->SetPersistentDescriptor(utf8String); if (NS_SUCCEEDED(rv)) { nsILocalFile *temp = file; NS_ADDREF(temp); *_retval = (void *)temp; return NS_OK; } } return rv; } if (aType.Equals(NS_GET_IID(nsIRelativeFilePref))) { nsACString::const_iterator keyBegin, strEnd; utf8String.BeginReading(keyBegin); utf8String.EndReading(strEnd); // The pref has the format: [fromKey]a/b/c if (*keyBegin++ != '[') return NS_ERROR_FAILURE; nsACString::const_iterator keyEnd(keyBegin); if (!FindCharInReadable(']', keyEnd, strEnd)) return NS_ERROR_FAILURE; nsCAutoString key(Substring(keyBegin, keyEnd)); nsCOMPtr<nsILocalFile> fromFile; nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; rv = directoryService->Get(key.get(), NS_GET_IID(nsILocalFile), getter_AddRefs(fromFile)); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsILocalFile> theFile; rv = NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(theFile)); if (NS_FAILED(rv)) return rv; rv = theFile->SetRelativeDescriptor(fromFile, Substring(++keyEnd, strEnd)); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIRelativeFilePref> relativePref; rv = NS_NewRelativeFilePref(theFile, key, getter_AddRefs(relativePref)); if (NS_FAILED(rv)) return rv; *_retval = relativePref; NS_ADDREF(NS_STATIC_CAST(nsIRelativeFilePref*, *_retval)); return NS_OK; }