void MultipartBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv) { *aStream = nullptr; nsCOMPtr<nsIMultiplexInputStream> stream = do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1"); if (NS_WARN_IF(!stream)) { aRv.Throw(NS_ERROR_FAILURE); return; } uint32_t i; for (i = 0; i < mBlobImpls.Length(); i++) { nsCOMPtr<nsIInputStream> scratchStream; BlobImpl* blobImpl = mBlobImpls.ElementAt(i).get(); blobImpl->GetInternalStream(getter_AddRefs(scratchStream), aRv); if (NS_WARN_IF(aRv.Failed())) { return; } aRv = stream->AppendStream(scratchStream); if (NS_WARN_IF(aRv.Failed())) { return; } } stream.forget(aStream); }
void MultipartBlobImpl::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) { if (!mIsFromNsIFile || mBlobImpls.Length() == 0) { BlobImplBase::GetMozFullPathInternal(aFilename, aRv); return; } BlobImpl* blobImpl = mBlobImpls.ElementAt(0).get(); if (!blobImpl) { BlobImplBase::GetMozFullPathInternal(aFilename, aRv); return; } blobImpl->GetMozFullPathInternal(aFilename, aRv); }
nsresult nsFileControlFrame::DnDListener::GetBlobImplForWebkitDirectory(nsIDOMFileList* aFileList, BlobImpl** aBlobImpl) { *aBlobImpl = nullptr; HTMLInputElement* inputElement = HTMLInputElement::FromContent(mFrame->GetContent()); bool webkitDirPicker = Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) && inputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory); if (!webkitDirPicker) { return NS_OK; } if (!aFileList) { return NS_ERROR_FAILURE; } FileList* files = static_cast<FileList*>(aFileList); // webkitdirectory doesn't care about the length of the file list but // only about the first item on it. uint32_t len = files->Length(); if (len) { File* file = files->Item(0); if (file) { BlobImpl* impl = file->Impl(); if (impl && impl->IsDirectory()) { RefPtr<BlobImpl> retVal = impl; retVal.swap(*aBlobImpl); return NS_OK; } } } return NS_ERROR_FAILURE; }
void RowImpl::SetValue(int varnum, IITYPE ivType, const void* value, int userlen) { if (varnum < 1 || varnum > mDescrArea->sqld) throw LogicExceptionImpl("RowImpl::SetValue", _("Variable index out of range.")); if (value == 0) throw LogicExceptionImpl("RowImpl::SetValue", _("Unexpected null pointer detected.")); int16_t len; XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); switch (var->sqltype & ~1) { case SQL_TEXT : if (ivType == ivString) { std::string* svalue = (std::string*)value; len = (int16_t)svalue->length(); if (len > var->sqllen) len = var->sqllen; strncpy(var->sqldata, svalue->c_str(), len); while (len < var->sqllen) var->sqldata[len++] = ' '; } else if (ivType == ivByte) { if (userlen > var->sqllen) userlen = var->sqllen; memcpy(var->sqldata, value, userlen); while (userlen < var->sqllen) var->sqldata[userlen++] = ' '; } else if (ivType == ivDBKey) { IBPP::DBKey* key = (IBPP::DBKey*)value; key->GetKey(var->sqldata, var->sqllen); } else if (ivType == ivBool) { var->sqldata[0] = *(bool*)value ? 'T' : 'F'; len = 1; while (len < var->sqllen) var->sqldata[len++] = ' '; } else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_VARYING : if (ivType == ivString) { std::string* svalue = (std::string*)value; len = (int16_t)svalue->length(); if (len > var->sqllen) len = var->sqllen; *(int16_t*)var->sqldata = (int16_t)len; strncpy(var->sqldata+2, svalue->c_str(), len); } else if (ivType == ivByte) { if (userlen > var->sqllen) userlen = var->sqllen; *(int16_t*)var->sqldata = (int16_t)userlen; memcpy(var->sqldata+2, value, userlen); } else if (ivType == ivBool) { *(int16_t*)var->sqldata = (int16_t)1; var->sqldata[2] = *(bool*)value ? 'T' : 'F'; } else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_SHORT : if (ivType == ivBool) { *(int16_t*)var->sqldata = int16_t(*(bool*)value ? 1 : 0); } else if (ivType == ivInt16) { *(int16_t*)var->sqldata = *(int16_t*)value; } else if (ivType == ivInt32) { if (*(int32_t*)value < consts::min16 || *(int32_t*)value > consts::max16) throw LogicExceptionImpl("RowImpl::SetValue", _("Out of range numeric conversion !")); *(int16_t*)var->sqldata = (int16_t)*(int32_t*)value; } else if (ivType == ivInt64) { if (*(int64_t*)value < consts::min16 || *(int64_t*)value > consts::max16) throw LogicExceptionImpl("RowImpl::SetValue", _("Out of range numeric conversion !")); *(int16_t*)var->sqldata = (int16_t)*(int64_t*)value; } else if (ivType == ivFloat) { // This SQL_SHORT is a NUMERIC(x,y), scale it ! double multiplier = consts::dscales[-var->sqlscale]; *(int16_t*)var->sqldata = (int16_t)floor(*(float*)value * multiplier + 0.5); } else if (ivType == ivDouble) { // This SQL_SHORT is a NUMERIC(x,y), scale it ! double multiplier = consts::dscales[-var->sqlscale]; *(int16_t*)var->sqldata = (int16_t)floor(*(double*)value * multiplier + 0.5); } else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_LONG : if (ivType == ivBool) { *(ISC_LONG*)var->sqldata = *(bool*)value ? 1 : 0; } else if (ivType == ivInt16) { *(ISC_LONG*)var->sqldata = *(int16_t*)value; } else if (ivType == ivInt32) { *(ISC_LONG*)var->sqldata = *(ISC_LONG*)value; } else if (ivType == ivInt64) { if (*(int64_t*)value < consts::min32 || *(int64_t*)value > consts::max32) throw LogicExceptionImpl("RowImpl::SetValue", _("Out of range numeric conversion !")); *(ISC_LONG*)var->sqldata = (ISC_LONG)*(int64_t*)value; } else if (ivType == ivFloat) { // This SQL_LONG is a NUMERIC(x,y), scale it ! double multiplier = consts::dscales[-var->sqlscale]; *(ISC_LONG*)var->sqldata = (ISC_LONG)floor(*(float*)value * multiplier + 0.5); } else if (ivType == ivDouble) { // This SQL_LONG is a NUMERIC(x,y), scale it ! double multiplier = consts::dscales[-var->sqlscale]; *(ISC_LONG*)var->sqldata = (ISC_LONG)floor(*(double*)value * multiplier + 0.5); } else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_INT64 : if (ivType == ivBool) { *(int64_t*)var->sqldata = *(bool*)value ? 1 : 0; } else if (ivType == ivInt16) { *(int64_t*)var->sqldata = *(int16_t*)value; } else if (ivType == ivInt32) { *(int64_t*)var->sqldata = *(int32_t*)value; } else if (ivType == ivInt64) { *(int64_t*)var->sqldata = *(int64_t*)value; } else if (ivType == ivFloat) { // This SQL_INT64 is a NUMERIC(x,y), scale it ! double multiplier = consts::dscales[-var->sqlscale]; *(int64_t*)var->sqldata = (int64_t)floor(*(float*)value * multiplier + 0.5); } else if (ivType == ivDouble) { // This SQL_INT64 is a NUMERIC(x,y), scale it ! double multiplier = consts::dscales[-var->sqlscale]; *(int64_t*)var->sqldata = (int64_t)floor(*(double*)value * multiplier + 0.5); } else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_FLOAT : if (ivType != ivFloat || var->sqlscale != 0) throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); *(float*)var->sqldata = *(float*)value; break; case SQL_DOUBLE : if (ivType != ivDouble) throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); if (var->sqlscale != 0) { // Round to scale of NUMERIC(x,y) double multiplier = consts::dscales[-var->sqlscale]; *(double*)var->sqldata = floor(*(double*)value * multiplier + 0.5) / multiplier; } else *(double*)var->sqldata = *(double*)value; break; case SQL_TIMESTAMP : if (ivType != ivTimestamp) throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); encodeTimestamp(*(ISC_TIMESTAMP*)var->sqldata, *(IBPP::Timestamp*)value); break; case SQL_TYPE_DATE : if (ivType != ivDate) throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); encodeDate(*(ISC_DATE*)var->sqldata, *(IBPP::Date*)value); break; case SQL_TYPE_TIME : if (ivType != ivTime) throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); encodeTime(*(ISC_TIME*)var->sqldata, *(IBPP::Time*)value); break; case SQL_BLOB : if (ivType == ivBlob) { BlobImpl* blob = (BlobImpl*)value; blob->GetId((ISC_QUAD*)var->sqldata); } else if (ivType == ivString) { BlobImpl blob(mDatabase, mTransaction); blob.Save(*(std::string*)value); blob.GetId((ISC_QUAD*)var->sqldata); } else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_ARRAY : if (ivType != ivArray) throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); { ArrayImpl* array = (ArrayImpl*)value; array->GetId((ISC_QUAD*)var->sqldata); // When an array has been affected to a column, we want to reset // its ID. This way, the next WriteFrom() on the same Array object // will allocate a new ID. This protects against storing the same // array ID in multiple columns or rows. array->ResetId(); } break; default : throw LogicExceptionImpl("RowImpl::SetValue", _("The field uses an unsupported SQL type !")); } if (var->sqltype & 1) *var->sqlind = 0; // Remove the 0 flag }
void* RowImpl::GetValue(int varnum, IITYPE ivType, void* retvalue) { if (varnum < 1 || varnum > mDescrArea->sqld) throw LogicExceptionImpl("RowImpl::GetValue", _("Variable index out of range.")); void* value; int len; XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); // When there is no value (SQL NULL) if ((var->sqltype & 1) && *(var->sqlind) != 0) return 0; switch (var->sqltype & ~1) { case SQL_TEXT : if (ivType == ivString) { // In case of ivString, 'void* retvalue' points to a std::string where we // will directly store the data. std::string* str = (std::string*)retvalue; str->erase(); str->append(var->sqldata, var->sqllen); value = retvalue; // value != 0 means 'not null' } else if (ivType == ivByte) { // In case of ivByte, void* retvalue points to an int where we // will store the len of the available data if (retvalue != 0) *(int*)retvalue = var->sqllen; value = var->sqldata; } else if (ivType == ivDBKey) { IBPP::DBKey* key = (IBPP::DBKey*)retvalue; key->SetKey(var->sqldata, var->sqllen); value = retvalue; } else if (ivType == ivBool) { mBools[varnum-1] = 0; if (var->sqllen >= 1) { char c = var->sqldata[0]; if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1') mBools[varnum-1] = 1; } value = &mBools[varnum-1]; } else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_VARYING : if (ivType == ivString) { // In case of ivString, 'void* retvalue' points to a std::string where we // will directly store the data. std::string* str = (std::string*)retvalue; str->erase(); str->append(var->sqldata+2, (int32_t)*(int16_t*)var->sqldata); value = retvalue; } else if (ivType == ivByte) { // In case of ivByte, void* retvalue points to an int where we // will store the len of the available data if (retvalue != 0) *(int*)retvalue = (int)*(int16_t*)var->sqldata; value = var->sqldata+2; } else if (ivType == ivBool) { mBools[varnum-1] = 0; len = *(int16_t*)var->sqldata; if (len >= 1) { char c = var->sqldata[2]; if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1') mBools[varnum-1] = 1; } value = &mBools[varnum-1]; } else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_SHORT : if (ivType == ivInt16) { value = var->sqldata; } else if (ivType == ivBool) { if (*(int16_t*)var->sqldata == 0) mBools[varnum-1] = 0; else mBools[varnum-1] = 1; value = &mBools[varnum-1]; } else if (ivType == ivInt32) { mInt32s[varnum-1] = *(int16_t*)var->sqldata; value = &mInt32s[varnum-1]; } else if (ivType == ivInt64) { mInt64s[varnum-1] = *(int16_t*)var->sqldata; value = &mInt64s[varnum-1]; } else if (ivType == ivFloat) { // This SQL_SHORT is a NUMERIC(x,y), scale it ! double divisor = consts::dscales[-var->sqlscale]; mFloats[varnum-1] = (float)(*(int16_t*)var->sqldata / divisor); value = &mFloats[varnum-1]; } else if (ivType == ivDouble) { // This SQL_SHORT is a NUMERIC(x,y), scale it ! double divisor = consts::dscales[-var->sqlscale]; mNumerics[varnum-1] = *(int16_t*)var->sqldata / divisor; value = &mNumerics[varnum-1]; } else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_LONG : if (ivType == ivInt32) { value = var->sqldata; } else if (ivType == ivBool) { if (*(int32_t*)var->sqldata == 0) mBools[varnum-1] = 0; else mBools[varnum-1] = 1; value = &mBools[varnum-1]; } else if (ivType == ivInt16) { int32_t tmp = *(int32_t*)var->sqldata; if (tmp < consts::min16 || tmp > consts::max16) throw LogicExceptionImpl("RowImpl::GetValue", _("Out of range numeric conversion !")); mInt16s[varnum-1] = (int16_t)tmp; value = &mInt16s[varnum-1]; } else if (ivType == ivInt64) { mInt64s[varnum-1] = *(int32_t*)var->sqldata; value = &mInt64s[varnum-1]; } else if (ivType == ivFloat) { // This SQL_LONG is a NUMERIC(x,y), scale it ! double divisor = consts::dscales[-var->sqlscale]; mFloats[varnum-1] = (float)(*(int32_t*)var->sqldata / divisor); value = &mFloats[varnum-1]; } else if (ivType == ivDouble) { // This SQL_LONG is a NUMERIC(x,y), scale it ! double divisor = consts::dscales[-var->sqlscale]; mNumerics[varnum-1] = *(int32_t*)var->sqldata / divisor; value = &mNumerics[varnum-1]; } else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_INT64 : if (ivType == ivInt64) { value = var->sqldata; } else if (ivType == ivBool) { if (*(int64_t*)var->sqldata == 0) mBools[varnum-1] = 0; else mBools[varnum-1] = 1; value = &mBools[varnum-1]; } else if (ivType == ivInt16) { int64_t tmp = *(int64_t*)var->sqldata; if (tmp < consts::min16 || tmp > consts::max16) throw LogicExceptionImpl("RowImpl::GetValue", _("Out of range numeric conversion !")); mInt16s[varnum-1] = (int16_t)tmp; value = &mInt16s[varnum-1]; } else if (ivType == ivInt32) { int64_t tmp = *(int64_t*)var->sqldata; if (tmp < consts::min32 || tmp > consts::max32) throw LogicExceptionImpl("RowImpl::GetValue", _("Out of range numeric conversion !")); mInt32s[varnum-1] = (int32_t)tmp; value = &mInt32s[varnum-1]; } else if (ivType == ivFloat) { // This SQL_INT64 is a NUMERIC(x,y), scale it ! double divisor = consts::dscales[-var->sqlscale]; mFloats[varnum-1] = (float)(*(int64_t*)var->sqldata / divisor); value = &mFloats[varnum-1]; } else if (ivType == ivDouble) { // This SQL_INT64 is a NUMERIC(x,y), scale it ! double divisor = consts::dscales[-var->sqlscale]; mNumerics[varnum-1] = *(int64_t*)var->sqldata / divisor; value = &mNumerics[varnum-1]; } else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_FLOAT : if (ivType != ivFloat) throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, _("Incompatible types.")); value = var->sqldata; break; case SQL_DOUBLE : if (ivType != ivDouble) throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, _("Incompatible types.")); if (var->sqlscale != 0) { // Round to scale y of NUMERIC(x,y) double multiplier = consts::dscales[-var->sqlscale]; mNumerics[varnum-1] = floor(*(double*)var->sqldata * multiplier + 0.5) / multiplier; value = &mNumerics[varnum-1]; } else value = var->sqldata; break; case SQL_TIMESTAMP : if (ivType != ivTimestamp) throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); decodeTimestamp(*(IBPP::Timestamp*)retvalue, *(ISC_TIMESTAMP*)var->sqldata); value = retvalue; break; case SQL_TYPE_DATE : if (ivType != ivDate) throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); decodeDate(*(IBPP::Date*)retvalue, *(ISC_DATE*)var->sqldata); value = retvalue; break; case SQL_TYPE_TIME : if (ivType != ivTime) throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, _("Incompatible types.")); decodeTime(*(IBPP::Time*)retvalue, *(ISC_TIME*)var->sqldata); value = retvalue; break; case SQL_BLOB : if (ivType == ivBlob) { BlobImpl* blob = (BlobImpl*)retvalue; blob->SetId((ISC_QUAD*)var->sqldata); value = retvalue; } else if (ivType == ivString) { BlobImpl blob(mDatabase, mTransaction); blob.SetId((ISC_QUAD*)var->sqldata); std::string* str = (std::string*)retvalue; blob.Load(*str); value = retvalue; } else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, _("Incompatible types.")); break; case SQL_ARRAY : if (ivType != ivArray) throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, _("Incompatible types.")); { ArrayImpl* array = (ArrayImpl*)retvalue; array->SetId((ISC_QUAD*)var->sqldata); value = retvalue; } break; default : throw LogicExceptionImpl("RowImpl::GetValue", _("Found an unknown sqltype !")); } return value; }
already_AddRefed<BlobImpl> MultipartBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType, ErrorResult& aRv) { // If we clamped to nothing we create an empty blob nsTArray<nsRefPtr<BlobImpl>> blobImpls; uint64_t length = aLength; uint64_t skipStart = aStart; // Prune the list of blobs if we can uint32_t i; for (i = 0; length && skipStart && i < mBlobImpls.Length(); i++) { BlobImpl* blobImpl = mBlobImpls[i].get(); uint64_t l = blobImpl->GetSize(aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } if (skipStart < l) { uint64_t upperBound = std::min<uint64_t>(l - skipStart, length); nsRefPtr<BlobImpl> firstBlobImpl = blobImpl->CreateSlice(skipStart, upperBound, aContentType, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } // Avoid wrapping a single blob inside an MultipartBlobImpl if (length == upperBound) { return firstBlobImpl.forget(); } blobImpls.AppendElement(firstBlobImpl); length -= upperBound; i++; break; } skipStart -= l; } // Now append enough blobs until we're done for (; length && i < mBlobImpls.Length(); i++) { BlobImpl* blobImpl = mBlobImpls[i].get(); uint64_t l = blobImpl->GetSize(aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } if (length < l) { nsRefPtr<BlobImpl> lastBlobImpl = blobImpl->CreateSlice(0, length, aContentType, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } blobImpls.AppendElement(lastBlobImpl); } else { blobImpls.AppendElement(blobImpl); } length -= std::min<uint64_t>(l, length); } // we can create our blob now nsRefPtr<BlobImpl> impl = new MultipartBlobImpl(blobImpls, aContentType); return impl.forget(); }
nsresult FetchDriver::BasicFetch() { nsAutoCString url; mRequest->GetURL(url); nsCOMPtr<nsIURI> uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); return rv; } nsAutoCString scheme; rv = uri->GetScheme(scheme); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); return rv; } if (scheme.LowerCaseEqualsLiteral("about")) { if (url.EqualsLiteral("about:blank")) { nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK")); ErrorResult result; response->Headers()->Append(NS_LITERAL_CSTRING("content-type"), NS_LITERAL_CSTRING("text/html;charset=utf-8"), result); MOZ_ASSERT(!result.Failed()); nsCOMPtr<nsIInputStream> body; rv = NS_NewCStringInputStream(getter_AddRefs(body), EmptyCString()); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); return rv; } response->SetBody(body); BeginResponse(response); return SucceedWithResponse(); } return FailWithNetworkError(); } if (scheme.LowerCaseEqualsLiteral("blob")) { nsRefPtr<BlobImpl> blobImpl; rv = NS_GetBlobForBlobURI(uri, getter_AddRefs(blobImpl)); BlobImpl* blob = static_cast<BlobImpl*>(blobImpl.get()); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); return rv; } nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK")); ErrorResult result; uint64_t size = blob->GetSize(result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); return result.StealNSResult(); } nsAutoString sizeStr; sizeStr.AppendInt(size); response->Headers()->Append(NS_LITERAL_CSTRING("Content-Length"), NS_ConvertUTF16toUTF8(sizeStr), result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); return result.StealNSResult(); } nsAutoString type; blob->GetType(type); response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), NS_ConvertUTF16toUTF8(type), result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); return result.StealNSResult(); } nsCOMPtr<nsIInputStream> stream; blob->GetInternalStream(getter_AddRefs(stream), result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); return result.StealNSResult(); } response->SetBody(stream); BeginResponse(response); return SucceedWithResponse(); } if (scheme.LowerCaseEqualsLiteral("data")) { nsAutoCString method; mRequest->GetMethod(method); if (method.LowerCaseEqualsASCII("get")) { nsresult rv; nsCOMPtr<nsIProtocolHandler> dataHandler = do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "data", &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return FailWithNetworkError(); } nsCOMPtr<nsIChannel> channel; rv = dataHandler->NewChannel(uri, getter_AddRefs(channel)); if (NS_WARN_IF(NS_FAILED(rv))) { return FailWithNetworkError(); } nsCOMPtr<nsIInputStream> stream; rv = channel->Open(getter_AddRefs(stream)); if (NS_WARN_IF(NS_FAILED(rv))) { return FailWithNetworkError(); } // nsDataChannel will parse the data URI when it is Open()ed and set the // correct content type and charset. nsAutoCString contentType; if (NS_SUCCEEDED(channel->GetContentType(contentType))) { nsAutoCString charset; if (NS_SUCCEEDED(channel->GetContentCharset(charset)) && !charset.IsEmpty()) { contentType.AppendLiteral(";charset="); contentType.Append(charset); } } else { NS_WARNING("Could not get content type from data channel"); } nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK")); ErrorResult result; response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); return result.StealNSResult(); } response->SetBody(stream); BeginResponse(response); return SucceedWithResponse(); } return FailWithNetworkError(); } if (scheme.LowerCaseEqualsLiteral("http") || scheme.LowerCaseEqualsLiteral("https") || scheme.LowerCaseEqualsLiteral("app")) { return HttpFetch(); } return FailWithNetworkError(); }
already_AddRefed<FileSystemEntry> DataTransferItem::GetAsEntryWithPrincipal(nsIPrincipal* aPrincipal, ErrorResult& aRv) { RefPtr<File> file = GetAsFileWithPrincipal(aPrincipal, aRv); if (NS_WARN_IF(aRv.Failed()) || !file) { return nullptr; } nsCOMPtr<nsIGlobalObject> global; // This is annoying, but DataTransfer may have various things as parent. nsCOMPtr<EventTarget> target = do_QueryInterface(mDataTransfer->GetParentObject()); if (target) { global = target->GetOwnerGlobal(); } else { nsCOMPtr<nsIDOMEvent> event = do_QueryInterface(mDataTransfer->GetParentObject()); if (event) { global = event->InternalDOMEvent()->GetParentObject(); } } if (!global) { return nullptr; } RefPtr<FileSystem> fs = FileSystem::Create(global); RefPtr<FileSystemEntry> entry; BlobImpl* impl = file->Impl(); MOZ_ASSERT(impl); if (impl->IsDirectory()) { nsAutoString fullpath; impl->GetMozFullPathInternal(fullpath, aRv); if (aRv.Failed()) { aRv.SuppressException(); return nullptr; } nsCOMPtr<nsIFile> directoryFile; nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(fullpath), true, getter_AddRefs(directoryFile)); if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; } RefPtr<Directory> directory = Directory::Create(global, directoryFile); entry = new FileSystemDirectoryEntry(global, directory, fs); } else { entry = new FileSystemFileEntry(global, file, fs); } Sequence<RefPtr<FileSystemEntry>> entries; if (!entries.AppendElement(entry, fallible)) { return nullptr; } fs->CreateRoot(entries); return entry.forget(); }
nsresult FetchDriver::BasicFetch() { nsAutoCString url; mRequest->GetURL(url); nsCOMPtr<nsIURI> uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); return rv; } nsAutoCString scheme; rv = uri->GetScheme(scheme); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); return rv; } if (scheme.LowerCaseEqualsLiteral("about")) { if (url.EqualsLiteral("about:blank")) { nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK")); ErrorResult result; response->Headers()->Append(NS_LITERAL_CSTRING("content-type"), NS_LITERAL_CSTRING("text/html;charset=utf-8"), result); MOZ_ASSERT(!result.Failed()); nsCOMPtr<nsIInputStream> body; rv = NS_NewCStringInputStream(getter_AddRefs(body), EmptyCString()); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); return rv; } response->SetBody(body); BeginResponse(response); return SucceedWithResponse(); } return FailWithNetworkError(); } if (scheme.LowerCaseEqualsLiteral("blob")) { nsRefPtr<BlobImpl> blobImpl; rv = NS_GetBlobForBlobURI(uri, getter_AddRefs(blobImpl)); BlobImpl* blob = static_cast<BlobImpl*>(blobImpl.get()); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); return rv; } nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK")); ErrorResult result; uint64_t size = blob->GetSize(result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); return result.StealNSResult(); } nsAutoString sizeStr; sizeStr.AppendInt(size); response->Headers()->Append(NS_LITERAL_CSTRING("Content-Length"), NS_ConvertUTF16toUTF8(sizeStr), result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); return result.StealNSResult(); } nsAutoString type; blob->GetType(type); response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), NS_ConvertUTF16toUTF8(type), result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); return result.StealNSResult(); } nsCOMPtr<nsIInputStream> stream; blob->GetInternalStream(getter_AddRefs(stream), result); if (NS_WARN_IF(result.Failed())) { FailWithNetworkError(); return result.StealNSResult(); } response->SetBody(stream); BeginResponse(response); return SucceedWithResponse(); } if (scheme.LowerCaseEqualsLiteral("data")) { nsAutoCString method; mRequest->GetMethod(method); if (method.LowerCaseEqualsASCII("get")) { // Use nsDataHandler directly so that we can extract the content type. // XXX(nsm): Is there a way to acquire the charset without such tight // coupling with the DataHandler? nsIProtocolHandler does not provide // anything similar. nsAutoCString contentType, contentCharset, dataBuffer, hashRef; bool isBase64; rv = nsDataHandler::ParseURI(url, contentType, contentCharset, isBase64, dataBuffer, hashRef); if (NS_SUCCEEDED(rv)) { ErrorResult result; nsRefPtr<InternalResponse> response = new InternalResponse(200, NS_LITERAL_CSTRING("OK")); if (!contentCharset.IsEmpty()) { contentType.Append(";charset="); contentType.Append(contentCharset); } response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, result); if (!result.Failed()) { nsCOMPtr<nsIInputStream> stream; rv = NS_NewCStringInputStream(getter_AddRefs(stream), dataBuffer); if (NS_SUCCEEDED(rv)) { response->SetBody(stream); BeginResponse(response); return SucceedWithResponse(); } } } } return FailWithNetworkError(); } if (scheme.LowerCaseEqualsLiteral("http") || scheme.LowerCaseEqualsLiteral("https") || scheme.LowerCaseEqualsLiteral("app")) { return HttpFetch(); } return FailWithNetworkError(); }
NS_DECL_ISUPPORTS NS_IMETHOD CollectReports(nsIHandleReportCallback* aCallback, nsISupports* aData, bool aAnonymize) override { if (!gDataTable) { return NS_OK; } nsDataHashtable<nsPtrHashKey<BlobImpl>, uint32_t> refCounts; // Determine number of URLs per BlobImpl, to handle the case where it's > 1. for (auto iter = gDataTable->Iter(); !iter.Done(); iter.Next()) { if (iter.UserData()->mObjectType != DataInfo::eBlobImpl) { continue; } BlobImpl* blobImpl = iter.UserData()->mBlobImpl; MOZ_ASSERT(blobImpl); refCounts.Put(blobImpl, refCounts.Get(blobImpl) + 1); } for (auto iter = gDataTable->Iter(); !iter.Done(); iter.Next()) { nsCStringHashKey::KeyType key = iter.Key(); DataInfo* info = iter.UserData(); if (iter.UserData()->mObjectType == DataInfo::eBlobImpl) { BlobImpl* blobImpl = iter.UserData()->mBlobImpl; MOZ_ASSERT(blobImpl); NS_NAMED_LITERAL_CSTRING(desc, "A blob URL allocated with URL.createObjectURL; the referenced " "blob cannot be freed until all URLs for it have been explicitly " "invalidated with URL.revokeObjectURL."); nsAutoCString path, url, owner, specialDesc; uint64_t size = 0; uint32_t refCount = 1; DebugOnly<bool> blobImplWasCounted; blobImplWasCounted = refCounts.Get(blobImpl, &refCount); MOZ_ASSERT(blobImplWasCounted); MOZ_ASSERT(refCount > 0); bool isMemoryFile = blobImpl->IsMemoryFile(); if (isMemoryFile) { ErrorResult rv; size = blobImpl->GetSize(rv); if (NS_WARN_IF(rv.Failed())) { rv.SuppressException(); size = 0; } } path = isMemoryFile ? "memory-blob-urls/" : "file-blob-urls/"; BuildPath(path, key, info, aAnonymize); if (refCount > 1) { nsAutoCString addrStr; addrStr = "0x"; addrStr.AppendInt((uint64_t)(BlobImpl*)blobImpl, 16); path += " "; path.AppendInt(refCount); path += "@"; path += addrStr; specialDesc = desc; specialDesc += "\n\nNOTE: This blob (address "; specialDesc += addrStr; specialDesc += ") has "; specialDesc.AppendInt(refCount); specialDesc += " URLs."; if (isMemoryFile) { specialDesc += " Its size is divided "; specialDesc += refCount > 2 ? "among" : "between"; specialDesc += " them in this report."; } } const nsACString& descString = specialDesc.IsEmpty() ? static_cast<const nsACString&>(desc) : static_cast<const nsACString&>(specialDesc); if (isMemoryFile) { aCallback->Callback(EmptyCString(), path, KIND_OTHER, UNITS_BYTES, size / refCount, descString, aData); } else { aCallback->Callback(EmptyCString(), path, KIND_OTHER, UNITS_COUNT, 1, descString, aData); } continue; } // Just report the path for the DOMMediaStream or MediaSource. nsAutoCString path; path = iter.UserData()->mObjectType == DataInfo::eMediaSource ? "media-source-urls/" : "dom-media-stream-urls/"; BuildPath(path, key, info, aAnonymize); NS_NAMED_LITERAL_CSTRING(desc, "An object URL allocated with URL.createObjectURL; the referenced " "data cannot be freed until all URLs for it have been explicitly " "invalidated with URL.revokeObjectURL."); aCallback->Callback(EmptyCString(), path, KIND_OTHER, UNITS_COUNT, 1, desc, aData); } return NS_OK; }