import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1187146 - Replace nsBaseHashtable::Enumerate() calls in js/xpconnect/ with iterators. r=mrbkap. (28d2b6078d)
- Bug 1226119 - Clear pending exception from script cache writing failure. r=bholley (cca6220b3e)
- Bug 1218029 - Adds IncrementalStreamLoader interface stubs. r=djvj (d2eaf684d5)
- Bug 1218029 - Adds ScriptLoadHandler and implements OnIncrementalData callback. r=djvj (8f841b143d)
- Bug 1228467 - Don't preprocess dom/base/UseCounters.conf. r=froydnj (534610a94c)
- add EME bits to keep PP happy (47840e6c56)
This commit is contained in:
2023-04-24 11:03:39 +08:00
parent 5602866910
commit 0394c7f1d2
23 changed files with 636 additions and 85 deletions
+1 -3
View File
@@ -12,9 +12,7 @@
//
// (b) a comment, which is a line that begins with "//"
//
// (c) an #if/ifdef/else/endif preprocessor directive
//
// (d) one of three possible use counter declarations:
// (c) one of three possible use counter declarations:
//
// method <IDL interface name>.<IDL operation name>
// attribute <IDL interface name>.<IDL attribute name>
+46 -39
View File
@@ -157,10 +157,10 @@ nsScriptLoader::~nsScriptLoader()
// subtree in the meantime and therefore aren't actually going away.
for (uint32_t j = 0; j < mPendingChildLoaders.Length(); ++j) {
mPendingChildLoaders[j]->RemoveExecuteBlocker();
}
}
}
NS_IMPL_ISUPPORTS(nsScriptLoader, nsIStreamLoaderObserver)
NS_IMPL_ISUPPORTS(nsScriptLoader, nsISupports)
// Helper method for checking if the script element is an event-handler
// This means that it has both a for-attribute and a event-attribute.
@@ -269,37 +269,6 @@ nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument,
return NS_OK;
}
class ContextMediator : public nsIStreamLoaderObserver
{
public:
explicit ContextMediator(nsScriptLoader *aScriptLoader, nsISupports *aContext)
: mScriptLoader(aScriptLoader)
, mContext(aContext) {}
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLOADEROBSERVER
private:
virtual ~ContextMediator() {}
RefPtr<nsScriptLoader> mScriptLoader;
nsCOMPtr<nsISupports> mContext;
};
NS_IMPL_ISUPPORTS(ContextMediator, nsIStreamLoaderObserver)
NS_IMETHODIMP
ContextMediator::OnStreamComplete(nsIStreamLoader* aLoader,
nsISupports* aContext,
nsresult aStatus,
uint32_t aStringLen,
const uint8_t* aString)
{
// pass arguments through except for the aContext,
// we have to mediate and use mContext instead.
return mScriptLoader->OnStreamComplete(aLoader, mContext, aStatus,
aStringLen, aString);
}
nsresult
nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
bool aScriptFromHead)
@@ -383,10 +352,10 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
timedChannel->SetInitiatorType(NS_LITERAL_STRING("script"));
}
RefPtr<ContextMediator> mediator = new ContextMediator(this, aRequest);
RefPtr<nsScriptLoadHandler> handler = new nsScriptLoadHandler(this, aRequest);
nsCOMPtr<nsIStreamLoader> loader;
rv = NS_NewStreamLoader(getter_AddRefs(loader), mediator);
nsCOMPtr<nsIIncrementalStreamLoader> loader;
rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), handler);
NS_ENSURE_SUCCESS(rv, rv);
return channel->AsyncOpen2(loader);
@@ -1453,8 +1422,8 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
return rv;
}
NS_IMETHODIMP
nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
nsresult
nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
nsISupports* aContext,
nsresult aStatus,
uint32_t aStringLen,
@@ -1550,7 +1519,7 @@ nsScriptLoader::NumberOfProcessors()
nsresult
nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
nsIStreamLoader* aLoader,
nsIIncrementalStreamLoader* aLoader,
nsresult aStatus,
uint32_t aStringLen,
const uint8_t* aString)
@@ -1757,3 +1726,41 @@ nsScriptLoader::MaybeRemovedDeferRequests()
}
return false;
}
//////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////
nsScriptLoadHandler::nsScriptLoadHandler(nsScriptLoader *aScriptLoader,
nsScriptLoadRequest *aRequest)
: mScriptLoader(aScriptLoader),
mRequest(aRequest)
{}
nsScriptLoadHandler::~nsScriptLoadHandler()
{}
NS_IMPL_ISUPPORTS(nsScriptLoadHandler, nsIIncrementalStreamLoaderObserver)
NS_IMETHODIMP
nsScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
nsISupports* aContext,
uint32_t aDataLength,
const uint8_t* aData,
uint32_t *aConsumedLength)
{
return NS_OK;
}
NS_IMETHODIMP
nsScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
nsISupports* aContext,
nsresult aStatus,
uint32_t aStringLen,
const uint8_t* aString)
{
// pass arguments through except for the aContext,
// we have to mediate and use mRequest instead.
return mScriptLoader->OnStreamComplete(aLoader, mRequest, aStatus,
aStringLen, aString);
}
+30 -4
View File
@@ -17,7 +17,7 @@
#include "nsTArray.h"
#include "nsAutoPtr.h"
#include "nsIDocument.h"
#include "nsIStreamLoader.h"
#include "nsIIncrementalStreamLoader.h"
#include "mozilla/CORSMode.h"
#include "mozilla/dom/SRIMetadata.h"
#include "mozilla/LinkedList.h"
@@ -195,7 +195,7 @@ public:
// Script loader implementation
//////////////////////////////////////////////////////////////
class nsScriptLoader final : public nsIStreamLoaderObserver
class nsScriptLoader final : public nsISupports
{
class MOZ_STACK_CLASS AutoCurrentScriptUpdater
{
@@ -223,7 +223,6 @@ public:
explicit nsScriptLoader(nsIDocument* aDocument);
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLOADEROBSERVER
/**
* The loader maintains a weak reference to the document with
@@ -342,6 +341,17 @@ public:
nsIDocument* aDocument,
char16_t*& aBufOut, size_t& aLengthOut);
/**
* Handle the completion of a stream. This is called by the
* nsScriptLoadHandler object which observes the IncrementalStreamLoader
* loading the script.
*/
nsresult OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
nsISupports* aContext,
nsresult aStatus,
uint32_t aStringLen,
const uint8_t* aString);
/**
* Processes any pending requests that are ready for processing.
*/
@@ -489,7 +499,7 @@ private:
uint32_t NumberOfProcessors();
nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
nsIStreamLoader* aLoader,
nsIIncrementalStreamLoader* aLoader,
nsresult aStatus,
uint32_t aStringLen,
const uint8_t* aString);
@@ -538,6 +548,22 @@ private:
bool mBlockingDOMContentLoaded;
};
class nsScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver
{
public:
explicit nsScriptLoadHandler(nsScriptLoader* aScriptLoader,
nsScriptLoadRequest *aRequest);
NS_DECL_ISUPPORTS
NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
private:
virtual ~nsScriptLoadHandler();
RefPtr<nsScriptLoader> mScriptLoader;
RefPtr<nsScriptLoadRequest> mRequest;
};
class nsAutoScriptLoaderDisabler
{
public:
+1 -10
View File
@@ -8,18 +8,9 @@ import re
import StringIO
import sys
from mozbuild.preprocessor import preprocess
def read_conf(conf_filename):
# Invoking the preprocessor ourselves is easier than writing build rules
# to do it for us.
processed = StringIO.StringIO()
preprocess(includes=[conf_filename],
defines=buildconfig.defines,
output=processed)
# Can't read/write from a single StringIO, so make a new one for reading.
stream = StringIO.StringIO(processed.getvalue())
stream = open(conf_filename, 'rU')
def parse_counters(stream):
for line_num, line in enumerate(stream):
+2 -2
View File
@@ -16,7 +16,7 @@
#include "nsIProtocolHandler.h"
#include "nsIScriptError.h"
#include "nsIScriptSecurityManager.h"
#include "nsIStreamLoader.h"
#include "nsIIncrementalStreamLoader.h"
#include "nsIUnicharStreamLoader.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
@@ -317,7 +317,7 @@ SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
/* static */ nsresult
SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
nsIStreamLoader* aLoader,
nsIIncrementalStreamLoader* aLoader,
const CORSMode aCORSMode,
uint32_t aStringLen,
const uint8_t* aString,
+2 -2
View File
@@ -12,7 +12,7 @@
#include "SRIMetadata.h"
class nsIDocument;
class nsIStreamLoader;
class nsIIncrementalStreamLoader;
class nsIUnicharStreamLoader;
namespace mozilla {
@@ -47,7 +47,7 @@ public:
* must prevent the resource from loading.
*/
static nsresult VerifyIntegrity(const SRIMetadata& aMetadata,
nsIStreamLoader* aLoader,
nsIIncrementalStreamLoader* aLoader,
const CORSMode aCORSMode,
uint32_t aStringLen,
const uint8_t* aString,
+14
View File
@@ -150,6 +150,20 @@ partial interface HTMLMediaElement {
attribute EventHandler onmozinterruptend;
};
#ifdef MOZ_EME
// Encrypted Media Extensions
partial interface HTMLMediaElement {
[Pref="media.eme.apiVisible"]
readonly attribute MediaKeys? mediaKeys;
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
[Pref="media.eme.apiVisible", NewObject]
Promise<void> setMediaKeys(MediaKeys? mediaKeys);
[Pref="media.eme.apiVisible"]
attribute EventHandler onencrypted;
};
#endif
// This is just for testing
partial interface HTMLMediaElement {
+1
View File
@@ -21,6 +21,7 @@
#include "nsIXULDocument.h"
#include "nsScriptLoader.h"
#include "nsIStreamListener.h"
#include "nsIStreamLoader.h"
#include "nsICSSLoaderObserver.h"
#include "nsIXULStore.h"
+4 -8
View File
@@ -964,13 +964,6 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo& aInfo,
return NS_OK;
}
/* static */ PLDHashOperator
mozJSComponentLoader::ClearModules(const nsACString& key, ModuleEntry*& entry, void* cx)
{
entry->Clear();
return PL_DHASH_REMOVE;
}
void
mozJSComponentLoader::UnloadModules()
{
@@ -1000,7 +993,10 @@ mozJSComponentLoader::UnloadModules()
mInProgressImports.Clear();
mImports.Clear();
mModules.Enumerate(ClearModules, nullptr);
for (auto iter = mModules.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->Clear();
iter.Remove();
}
}
NS_IMETHODIMP
@@ -148,7 +148,6 @@ class mozJSComponentLoader : public mozilla::ModuleLoader,
mozilla::MallocSizeOf aMallocSizeOf, void* arg);
// Modules are intentionally leaked, but still cleared.
static PLDHashOperator ClearModules(const nsACString& key, ModuleEntry*& entry, void* cx);
nsDataHashtable<nsCStringHashKey, ModuleEntry*> mModules;
nsClassHashtable<nsCStringHashKey, ModuleEntry> mImports;
+10 -4
View File
@@ -65,8 +65,11 @@ WriteCachedScript(StartupCache* cache, nsACString& uri, JSContext* cx,
uint32_t size;
void* data = JS_EncodeScript(cx, script, &size);
if (!data)
return NS_ERROR_OUT_OF_MEMORY;
if (!data) {
// JS_EncodeScript may have set a pending exception.
JS_ClearPendingException(cx);
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(size);
nsresult rv = cache->PutBuffer(PromiseFlatCString(uri).get(), static_cast<char*>(data), size);
@@ -83,8 +86,11 @@ WriteCachedFunction(StartupCache* cache, nsACString& uri, JSContext* cx,
uint32_t size;
void* data =
JS_EncodeInterpretedFunction(cx, JS_GetFunctionObject(function), &size);
if (!data)
return NS_ERROR_OUT_OF_MEMORY;
if (!data) {
// JS_EncodeInterpretedFunction may have set a pending exception.
JS_ClearPendingException(cx);
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(size);
nsresult rv = cache->PutBuffer(PromiseFlatCString(uri).get(), static_cast<char*>(data), size);
+32 -12
View File
@@ -239,11 +239,11 @@ EvalScript(JSContext* cx,
return NS_OK;
}
class AsyncScriptLoader : public nsIStreamLoaderObserver
class AsyncScriptLoader : public nsIIncrementalStreamLoaderObserver
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSISTREAMLOADEROBSERVER
NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AsyncScriptLoader)
@@ -277,7 +277,7 @@ private:
NS_IMPL_CYCLE_COLLECTION_CLASS(AsyncScriptLoader)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AsyncScriptLoader)
NS_INTERFACE_MAP_ENTRY(nsIStreamLoaderObserver)
NS_INTERFACE_MAP_ENTRY(nsIIncrementalStreamLoaderObserver)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AsyncScriptLoader)
@@ -326,7 +326,17 @@ class MOZ_STACK_CLASS AutoRejectPromise
};
NS_IMETHODIMP
AsyncScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
AsyncScriptLoader::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
nsISupports* aContext,
uint32_t aDataLength,
const uint8_t* aData,
uint32_t *aConsumedData)
{
return NS_OK;
}
NS_IMETHODIMP
AsyncScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
nsISupports* aContext,
nsresult aStatus,
uint32_t aLength,
@@ -431,8 +441,8 @@ mozJSSubScriptLoader::ReadScriptAsync(nsIURI* uri, JSObject* targetObjArg,
cache,
promise);
nsCOMPtr<nsIStreamLoader> loader;
rv = NS_NewStreamLoader(getter_AddRefs(loader), loadObserver);
nsCOMPtr<nsIIncrementalStreamLoader> loader;
rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), loadObserver);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStreamListener> listener = loader.get();
@@ -673,11 +683,11 @@ mozJSSubScriptLoader::DoLoadSubScriptWithOptions(const nsAString& url,
* Let us compile scripts from a URI off the main thread.
*/
class ScriptPrecompiler : public nsIStreamLoaderObserver
class ScriptPrecompiler : public nsIIncrementalStreamLoaderObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLOADEROBSERVER
NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
ScriptPrecompiler(nsIObserver* aObserver,
nsIPrincipal* aPrincipal,
@@ -709,7 +719,7 @@ private:
size_t mScriptLength;
};
NS_IMPL_ISUPPORTS(ScriptPrecompiler, nsIStreamLoaderObserver);
NS_IMPL_ISUPPORTS(ScriptPrecompiler, nsIIncrementalStreamLoaderObserver);
class NotifyPrecompilationCompleteRunnable : public nsRunnable
{
@@ -770,7 +780,17 @@ NotifyPrecompilationCompleteRunnable::Run(void)
}
NS_IMETHODIMP
ScriptPrecompiler::OnStreamComplete(nsIStreamLoader* aLoader,
ScriptPrecompiler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
nsISupports* aContext,
uint32_t aDataLength,
const uint8_t* aData,
uint32_t *aConsumedData)
{
return NS_OK;
}
NS_IMETHODIMP
ScriptPrecompiler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
nsISupports* aContext,
nsresult aStatus,
uint32_t aLength,
@@ -876,8 +896,8 @@ mozJSSubScriptLoader::PrecompileScript(nsIURI* aURI,
RefPtr<ScriptPrecompiler> loadObserver =
new ScriptPrecompiler(aObserver, aPrincipal, channel);
nsCOMPtr<nsIStreamLoader> loader;
rv = NS_NewStreamLoader(getter_AddRefs(loader), loadObserver);
nsCOMPtr<nsIIncrementalStreamLoader> loader;
rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), loadObserver);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStreamListener> listener = loader.get();
+2
View File
@@ -48,6 +48,7 @@ XPIDL_SOURCES += [
'nsIForcePendingChannel.idl',
'nsIHttpPushListener.idl',
'nsIIncrementalDownload.idl',
'nsIIncrementalStreamLoader.idl',
'nsIInputStreamChannel.idl',
'nsIInputStreamPump.idl',
'nsIIOService.idl',
@@ -212,6 +213,7 @@ UNIFIED_SOURCES += [
'nsDownloader.cpp',
'nsFileStreams.cpp',
'nsIncrementalDownload.cpp',
'nsIncrementalStreamLoader.cpp',
'nsInputStreamChannel.cpp',
'nsInputStreamPump.cpp',
'nsIOService.cpp',
+100
View File
@@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIStreamListener.idl"
interface nsIRequest;
interface nsIIncrementalStreamLoader;
[scriptable, uuid(07c3d2cc-5454-4618-9f4f-cd93de9504a4)]
interface nsIIncrementalStreamLoaderObserver : nsISupports
{
/**
* Called when new data has arrived on the stream.
*
* @param loader the stream loader that loaded the stream.
* @param ctxt the context parameter of the underlying channel
* @param dataLength the length of the new data received
* @param data the contents of the new data received.
*
* This method will always be called asynchronously by the
* nsIIncrementalStreamLoader involved, on the thread that called the
* loader's init() method.
*
* If the observer wants to not accumulate all or portional of the data in
* the internal buffer, the consumedLength shall be set to the value of
* the dataLength or less. By default the consumedLength value is assumed 0.
* The data and dataLength reflect the non-consumed data and will be
* accumulated if consumedLength is not set.
*
* In comparison with onStreamComplete(), the data buffer cannot be
* adopted if this method returns NS_SUCCESS_ADOPTED_DATA.
*/
void onIncrementalData(in nsIIncrementalStreamLoader loader,
in nsISupports ctxt,
in unsigned long dataLength,
[const,array,size_is(dataLength)] in octet data,
inout unsigned long consumedLength);
/**
* Called when the entire stream has been loaded.
*
* @param loader the stream loader that loaded the stream.
* @param ctxt the context parameter of the underlying channel
* @param status the status of the underlying channel
* @param resultLength the length of the data loaded
* @param result the data
*
* This method will always be called asynchronously by the
* nsIIncrementalStreamLoader involved, on the thread that called the
* loader's init() method.
*
* If the observer wants to take over responsibility for the
* data buffer (result), it returns NS_SUCCESS_ADOPTED_DATA
* in place of NS_OK as its success code. The loader will then
* "forget" about the data and not free() it after
* onStreamComplete() returns; observer must call free()
* when the data is no longer required.
*/
void onStreamComplete(in nsIIncrementalStreamLoader loader,
in nsISupports ctxt,
in nsresult status,
in unsigned long resultLength,
[const,array,size_is(resultLength)] in octet result);
};
/**
* Asynchronously loads a channel into a memory buffer.
*
* To use this interface, first call init() with a nsIIncrementalStreamLoaderObserver
* that will be notified when the data has been loaded. Then call asyncOpen()
* on the channel with the nsIIncrementalStreamLoader as the listener. The context
* argument in the asyncOpen() call will be passed to the onStreamComplete()
* callback.
*
* XXX define behaviour for sizes >4 GB
*/
[scriptable, uuid(a023b060-ba23-431a-b449-2dd63e220554)]
interface nsIIncrementalStreamLoader : nsIStreamListener
{
/**
* Initialize this stream loader, and start loading the data.
*
* @param aObserver
* An observer that will be notified when the data is complete.
*/
void init(in nsIIncrementalStreamLoaderObserver aObserver);
/**
* Gets the number of bytes read so far.
*/
readonly attribute unsigned long numBytesRead;
/**
* Gets the request that loaded this file.
* null after the request has finished loading.
*/
readonly attribute nsIRequest request;
};
+214
View File
@@ -0,0 +1,214 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIncrementalStreamLoader.h"
#include "nsIInputStream.h"
#include "nsIChannel.h"
#include "nsError.h"
#include "GeckoProfiler.h"
#include <limits>
nsIncrementalStreamLoader::nsIncrementalStreamLoader()
: mData(), mBytesConsumed(0)
{
}
nsIncrementalStreamLoader::~nsIncrementalStreamLoader()
{
}
NS_IMETHODIMP
nsIncrementalStreamLoader::Init(nsIIncrementalStreamLoaderObserver* observer)
{
NS_ENSURE_ARG_POINTER(observer);
mObserver = observer;
return NS_OK;
}
nsresult
nsIncrementalStreamLoader::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
if (aOuter) return NS_ERROR_NO_AGGREGATION;
nsIncrementalStreamLoader* it = new nsIncrementalStreamLoader();
if (it == nullptr)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(it);
nsresult rv = it->QueryInterface(aIID, aResult);
NS_RELEASE(it);
return rv;
}
NS_IMPL_ISUPPORTS(nsIncrementalStreamLoader, nsIIncrementalStreamLoader,
nsIRequestObserver, nsIStreamListener,
nsIThreadRetargetableStreamListener)
NS_IMETHODIMP
nsIncrementalStreamLoader::GetNumBytesRead(uint32_t* aNumBytes)
{
*aNumBytes = mBytesConsumed + mData.length();
return NS_OK;
}
/* readonly attribute nsIRequest request; */
NS_IMETHODIMP
nsIncrementalStreamLoader::GetRequest(nsIRequest **aRequest)
{
NS_IF_ADDREF(*aRequest = mRequest);
return NS_OK;
}
NS_IMETHODIMP
nsIncrementalStreamLoader::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
{
nsCOMPtr<nsIChannel> chan( do_QueryInterface(request) );
if (chan) {
int64_t contentLength = -1;
chan->GetContentLength(&contentLength);
if (contentLength >= 0) {
if (uint64_t(contentLength) > std::numeric_limits<size_t>::max()) {
// Too big to fit into size_t, so let's bail.
return NS_ERROR_OUT_OF_MEMORY;
}
// preallocate buffer
if (!mData.initCapacity(contentLength)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
}
mContext = ctxt;
return NS_OK;
}
NS_IMETHODIMP
nsIncrementalStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
nsresult aStatus)
{
PROFILER_LABEL("nsIncrementalStreamLoader", "OnStopRequest",
js::ProfileEntry::Category::NETWORK);
if (mObserver) {
// provide nsIIncrementalStreamLoader::request during call to OnStreamComplete
mRequest = request;
size_t length = mData.length();
uint8_t* elems = mData.extractRawBuffer();
nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus,
length, elems);
if (rv != NS_SUCCESS_ADOPTED_DATA) {
// The observer didn't take ownership of the extracted data buffer, so
// put it back into mData.
mData.replaceRawBuffer(elems, length);
}
// done.. cleanup
ReleaseData();
mRequest = 0;
mObserver = 0;
mContext = 0;
}
return NS_OK;
}
NS_METHOD
nsIncrementalStreamLoader::WriteSegmentFun(nsIInputStream *inStr,
void *closure,
const char *fromSegment,
uint32_t toOffset,
uint32_t count,
uint32_t *writeCount)
{
nsIncrementalStreamLoader *self = (nsIncrementalStreamLoader *) closure;
const uint8_t *data = reinterpret_cast<const uint8_t *>(fromSegment);
uint32_t consumedCount = 0;
nsresult rv;
if (self->mData.empty()) {
// Shortcut when observer wants to keep the listener's buffer empty.
rv = self->mObserver->OnIncrementalData(self, self->mContext,
count, data, &consumedCount);
if (rv != NS_OK) {
return rv;
}
if (consumedCount > count) {
return NS_ERROR_INVALID_ARG;
}
if (consumedCount < count) {
if (!self->mData.append(fromSegment + consumedCount,
count - consumedCount)) {
self->mData.clearAndFree();
return NS_ERROR_OUT_OF_MEMORY;
}
}
} else {
// We have some non-consumed data from previous OnIncrementalData call,
// appending new data and reporting combined data.
if (!self->mData.append(fromSegment, count)) {
self->mData.clearAndFree();
return NS_ERROR_OUT_OF_MEMORY;
}
size_t length = self->mData.length();
uint32_t reportCount = length > UINT32_MAX ? UINT32_MAX : (uint32_t)length;
uint8_t* elems = self->mData.extractRawBuffer();
rv = self->mObserver->OnIncrementalData(self, self->mContext,
reportCount, elems, &consumedCount);
// We still own elems, freeing its memory when exiting scope.
if (rv != NS_OK) {
free(elems);
return rv;
}
if (consumedCount > reportCount) {
free(elems);
return NS_ERROR_INVALID_ARG;
}
if (consumedCount == length) {
free(elems); // good case -- fully consumed data
} else {
// Adopting elems back (at least its portion).
self->mData.replaceRawBuffer(elems, length);
if (consumedCount > 0) {
self->mData.erase(self->mData.begin() + consumedCount);
}
}
}
self->mBytesConsumed += consumedCount;
*writeCount = count;
return NS_OK;
}
NS_IMETHODIMP
nsIncrementalStreamLoader::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
nsIInputStream *inStr,
uint64_t sourceOffset, uint32_t count)
{
if (mObserver) {
// provide nsIIncrementalStreamLoader::request during call to OnStreamComplete
mRequest = request;
}
uint32_t countRead;
nsresult rv = inStr->ReadSegments(WriteSegmentFun, this, count, &countRead);
mRequest = 0;
return rv;
}
void
nsIncrementalStreamLoader::ReleaseData()
{
mData.clearAndFree();
}
NS_IMETHODIMP
nsIncrementalStreamLoader::CheckListenerChain()
{
return NS_OK;
}
+54
View File
@@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsIncrementalStreamLoader_h__
#define nsIncrementalStreamLoader_h__
#include "nsIThreadRetargetableStreamListener.h"
#include "nsIIncrementalStreamLoader.h"
#include "nsCOMPtr.h"
#include "mozilla/Attributes.h"
#include "mozilla/Vector.h"
class nsIRequest;
class nsIncrementalStreamLoader final : public nsIIncrementalStreamLoader
, public nsIThreadRetargetableStreamListener
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINCREMENTALSTREAMLOADER
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
nsIncrementalStreamLoader();
static nsresult
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
protected:
~nsIncrementalStreamLoader();
static NS_METHOD WriteSegmentFun(nsIInputStream *, void *, const char *,
uint32_t, uint32_t, uint32_t *);
// Utility method to free mData, if present, and update other state to
// reflect that no data has been allocated.
void ReleaseData();
nsCOMPtr<nsIIncrementalStreamLoaderObserver> mObserver;
nsCOMPtr<nsISupports> mContext; // the observer's context
nsCOMPtr<nsIRequest> mRequest;
// Buffer to accumulate incoming data. We preallocate if contentSize is
// available.
mozilla::Vector<uint8_t, 0> mData;
// Number of consumed bytes from the mData.
size_t mBytesConsumed;
};
#endif // nsIncrementalStreamLoader_h__
+18
View File
@@ -45,6 +45,7 @@
#include "nsISocketProviderService.h"
#include "nsIStandardURL.h"
#include "nsIStreamLoader.h"
#include "nsIIncrementalStreamLoader.h"
#include "nsIStreamTransportService.h"
#include "nsStringStream.h"
#include "nsISyncStreamListener.h"
@@ -580,6 +581,23 @@ NS_NewDownloader(nsIStreamListener **result,
return rv;
}
nsresult
NS_NewIncrementalStreamLoader(nsIIncrementalStreamLoader **result,
nsIIncrementalStreamLoaderObserver *observer)
{
nsresult rv;
nsCOMPtr<nsIIncrementalStreamLoader> loader =
do_CreateInstance(NS_INCREMENTALSTREAMLOADER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = loader->Init(observer);
if (NS_SUCCEEDED(rv)) {
*result = nullptr;
loader.swap(*result);
}
}
return rv;
}
nsresult
NS_NewStreamLoaderInternal(nsIStreamLoader **outStream,
nsIURI *aUri,
+5
View File
@@ -42,6 +42,8 @@ class nsIRequestObserver;
class nsIStreamListener;
class nsIStreamLoader;
class nsIStreamLoaderObserver;
class nsIIncrementalStreamLoader;
class nsIIncrementalStreamLoaderObserver;
class nsIUnicharStreamLoader;
class nsIUnicharStreamLoaderObserver;
@@ -369,6 +371,9 @@ nsresult NS_NewStreamLoader(nsIStreamLoader **result,
nsIStreamLoaderObserver *observer,
nsIRequestObserver *requestObserver = nullptr);
nsresult NS_NewIncrementalStreamLoader(nsIIncrementalStreamLoader **result,
nsIIncrementalStreamLoaderObserver *observer);
nsresult NS_NewStreamLoaderInternal(nsIStreamLoader **outStream,
nsIURI *aUri,
nsIStreamLoaderObserver *aObserver,
+1
View File
@@ -23,6 +23,7 @@
#include "nsIProtocolHandler.h"
#include "nsIStandardURL.h"
#include "nsIStreamLoader.h"
#include "nsIIncrementalStreamLoader.h"
#include "nsIURI.h"
#include "nsIURIWithPrincipal.h"
#include "nsIWritablePropertyBag2.h"
+12
View File
@@ -226,6 +226,18 @@
{ 0xa1, 0xa5, 0x0, 0x50, 0x4, 0x1c, 0xaf, 0x44 } \
}
// component implementing nsIStreamLoader.
#define NS_INCREMENTALSTREAMLOADER_CONTRACTID \
"@mozilla.org/network/incremental-stream-loader;1"
#define NS_INCREMENTALSTREAMLOADER_CID \
{ /* 5d6352a3-b9c3-4fa3-87aa-b2a3c6e5a501 */ \
0x5d6352a3, \
0xb9c3, \
0x4fa3, \
{0x87, 0xaa, 0xb2, 0xa3, 0xc6, 0xe5, 0xa5, 0x01} \
}
// component implementing nsIUnicharStreamLoader.
#define NS_UNICHARSTREAMLOADER_CONTRACTID \
"@mozilla.org/network/unichar-stream-loader;1"
+4
View File
@@ -21,6 +21,7 @@
#include "nsSimpleNestedURI.h"
#include "nsLoadGroup.h"
#include "nsStreamLoader.h"
#include "nsIncrementalStreamLoader.h"
#include "nsUnicharStreamLoader.h"
#include "nsFileStreams.h"
#include "nsBufferedStreams.h"
@@ -707,6 +708,7 @@ NS_DEFINE_NAMED_CID(NS_ASYNCSTREAMCOPIER_CID);
NS_DEFINE_NAMED_CID(NS_INPUTSTREAMPUMP_CID);
NS_DEFINE_NAMED_CID(NS_INPUTSTREAMCHANNEL_CID);
NS_DEFINE_NAMED_CID(NS_STREAMLOADER_CID);
NS_DEFINE_NAMED_CID(NS_INCREMENTALSTREAMLOADER_CID);
NS_DEFINE_NAMED_CID(NS_UNICHARSTREAMLOADER_CID);
NS_DEFINE_NAMED_CID(NS_DOWNLOADER_CID);
NS_DEFINE_NAMED_CID(NS_BACKGROUNDFILESAVEROUTPUTSTREAM_CID);
@@ -854,6 +856,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
{ &kNS_INPUTSTREAMPUMP_CID, false, nullptr, nsInputStreamPumpConstructor },
{ &kNS_INPUTSTREAMCHANNEL_CID, false, nullptr, nsInputStreamChannelConstructor },
{ &kNS_STREAMLOADER_CID, false, nullptr, nsStreamLoader::Create },
{ &kNS_INCREMENTALSTREAMLOADER_CID, false, nullptr, nsIncrementalStreamLoader::Create },
{ &kNS_UNICHARSTREAMLOADER_CID, false, nullptr, nsUnicharStreamLoader::Create },
{ &kNS_DOWNLOADER_CID, false, nullptr, nsDownloaderConstructor },
{ &kNS_BACKGROUNDFILESAVEROUTPUTSTREAM_CID, false, nullptr,
@@ -1007,6 +1010,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
{ NS_INPUTSTREAMPUMP_CONTRACTID, &kNS_INPUTSTREAMPUMP_CID },
{ NS_INPUTSTREAMCHANNEL_CONTRACTID, &kNS_INPUTSTREAMCHANNEL_CID },
{ NS_STREAMLOADER_CONTRACTID, &kNS_STREAMLOADER_CID },
{ NS_INCREMENTALSTREAMLOADER_CONTRACTID, &kNS_INCREMENTALSTREAMLOADER_CID },
{ NS_UNICHARSTREAMLOADER_CONTRACTID, &kNS_UNICHARSTREAMLOADER_CID },
{ NS_DOWNLOADER_CONTRACTID, &kNS_DOWNLOADER_CID },
{ NS_BACKGROUNDFILESAVEROUTPUTSTREAM_CONTRACTID, &kNS_BACKGROUNDFILESAVEROUTPUTSTREAM_CID },
+82
View File
@@ -0,0 +1,82 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
var tests = [
{data: '', chunks: [], status: Cr.NS_OK, consume: [],
dataChunks: ['']},
{data: 'TWO-PARTS', chunks: [4, 5], status: Cr.NS_OK, consume: [4, 5],
dataChunks: ['TWO-', 'PARTS', '']},
{data: 'TWO-PARTS', chunks: [4, 5], status: Cr.NS_OK, consume: [0, 0],
dataChunks: ['TWO-', 'TWO-PARTS', 'TWO-PARTS']},
{data: '3-PARTS', chunks: [1, 1, 5], status: Cr.NS_OK, consume: [0, 2, 5],
dataChunks: ['3', '3-', 'PARTS', '']},
{data: 'ALL-AT-ONCE', chunks: [11], status: Cr.NS_OK, consume: [0],
dataChunks: ['ALL-AT-ONCE', 'ALL-AT-ONCE']},
{data: 'ALL-AT-ONCE', chunks: [11], status: Cr.NS_OK, consume: [11],
dataChunks: ['ALL-AT-ONCE', '']},
{data: 'ERROR', chunks: [1], status: Cr.NS_ERROR_OUT_OF_MEMORY, consume: [0],
dataChunks: ['E', 'E']}
];
/**
* @typedef TestData
* @property {string} data - data for the test.
* @property {Array} chunks - lengths of the chunks that are incrementally sent
* to the loader.
* @property {number} status - final status sent on onStopRequest.
* @property {Array} consume - lengths of consumed data that is reported at
* the onIncrementalData callback.
* @property {Array} dataChunks - data chunks that are reported at the
* onIncrementalData and onStreamComplete callbacks.
*/
function execute_test(test) {
let stream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
stream.data = test.data;
let channel = {
contentLength: -1,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel])
};
let chunkIndex = 0;
let observer = {
onStreamComplete: function(loader, context, status, length, data) {
equal(chunkIndex, test.dataChunks.length - 1);
var expectedChunk = test.dataChunks[chunkIndex];
equal(length, expectedChunk.length);
equal(String.fromCharCode.apply(null, data), expectedChunk);
equal(status, test.status);
},
onIncrementalData: function (loader, context, length, data, consumed) {
ok(chunkIndex < test.dataChunks.length - 1);
var expectedChunk = test.dataChunks[chunkIndex];
equal(length, expectedChunk.length);
equal(String.fromCharCode.apply(null, data), expectedChunk);
consumed.value = test.consume[chunkIndex];
chunkIndex++;
},
QueryInterface:
XPCOMUtils.generateQI([Ci.nsIIncrementalStreamLoaderObserver])
};
let listener = Cc["@mozilla.org/network/incremental-stream-loader;1"]
.createInstance(Ci.nsIIncrementalStreamLoader);
listener.init(observer);
listener.onStartRequest(channel, null);
var offset = 0;
test.chunks.forEach(function (chunkLength) {
listener.onDataAvailable(channel, null, stream, offset, chunkLength);
offset += chunkLength;
});
listener.onStopRequest(channel, null, test.status);
}
function run_test() {
tests.forEach(execute_test);
}
+1
View File
@@ -169,6 +169,7 @@ skip-if = os == "android"
skip-if = bits != 32
[test_bug935499.js]
[test_bug1064258.js]
[test_bug1218029.js]
[test_udpsocket.js]
[test_doomentry.js]
[test_cacheflags.js]