Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Ciure Andrei 2018-10-18 19:39:05 +03:00
commit e6f9a6308b
44 changed files with 324 additions and 201 deletions

View File

@ -125,6 +125,7 @@ public:
// These are mandatory.
NS_FORWARD_NSIINPUTSTREAM(mStream->)
NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
NS_FORWARD_NSITELLABLESTREAM(mSeekableStream->)
NS_FORWARD_NSICLONEABLEINPUTSTREAM(mCloneableInputStream->)
// This is optional. We use a conditional QI to keep it from being called

View File

@ -21,7 +21,6 @@ NS_IMPL_RELEASE_WITH_DESTROY(MediaTimer, DispatchDestroy())
MediaTimer::MediaTimer(bool aFuzzy)
: mMonitor("MediaTimer Monitor")
, mTimer(NS_NewTimer())
, mCreationTimeStamp(TimeStamp::Now())
, mUpdateScheduled(false)
, mFuzzy(aFuzzy)
@ -33,7 +32,7 @@ MediaTimer::MediaTimer(bool aFuzzy)
RefPtr<SharedThreadPool> threadPool(
SharedThreadPool::Get(NS_LITERAL_CSTRING("MediaTimer"), 1));
mThread = threadPool.get();
mTimer->SetTarget(mThread);
mTimer = NS_NewTimer(mThread);
}
void

View File

@ -23,15 +23,15 @@ struct FeatureMap {
*/
static FeatureMap sSupportedFeatures[] = {
{ "autoplay", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "camera", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "camera", FeaturePolicyUtils::FeaturePolicyValue::eSelf },
{ "encrypted-media", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "fullscreen", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "geolocation", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "microphone", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "midi", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "microphone", FeaturePolicyUtils::FeaturePolicyValue::eSelf },
{ "midi", FeaturePolicyUtils::FeaturePolicyValue::eSelf },
{ "payment", FeaturePolicyUtils::FeaturePolicyValue::eAll },
// TODO: not supported yet!!!
{ "speaker", FeaturePolicyUtils::FeaturePolicyValue::eAll },
{ "speaker", FeaturePolicyUtils::FeaturePolicyValue::eSelf },
{ "vr", FeaturePolicyUtils::FeaturePolicyValue::eAll },
};

View File

@ -18,15 +18,15 @@ function test_document() {
ok(!document.policy.allowsFeature("foobar"), "Random feature");
ok(!document.policy.allowsFeature("foobar", "http://www.something.net"), "Random feature");
ok(document.policy.allowsFeature("camera"), "Camera is always enabled");
ok(document.policy.allowsFeature("camera", "http://foo.bar"), "Camera is always enabled");
ok(document.policy.allowsFeature("camera"), "Camera is allowed for self");
ok(document.policy.allowsFeature("camera", "http://foo.bar"), "Camera is always allowed");
let allowed = document.policy.getAllowlistForFeature("camera");
is(allowed.length, 1, "Only 1 entry in allowlist for camera");
is(allowed[0], "*", "allowlist is *");
ok(document.policy.allowsFeature("geolocation"), "Geolocation is enabled for self");
ok(document.policy.allowsFeature("geolocation", location.origin), "Geolocation is enabled for self");
ok(!document.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is not enabled for any random URL");
ok(document.policy.allowsFeature("geolocation"), "Geolocation is allowed for self");
ok(document.policy.allowsFeature("geolocation", location.origin), "Geolocation is allowed for self");
ok(!document.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is not allowed for any random URL");
allowed = document.policy.getAllowlistForFeature("geolocation");
is(allowed.length, 1, "Only 1 entry in allowlist for geolocation");
is(allowed[0], location.origin, "allowlist is self");
@ -34,8 +34,8 @@ function test_document() {
ok(!document.policy.allowsFeature("microphone"), "Microphone is disabled for self");
ok(!document.policy.allowsFeature("microphone", location.origin), "Microphone is disabled for self");
ok(!document.policy.allowsFeature("microphone", "http://foo.bar"), "Microphone is disabled for foo.bar");
ok(document.policy.allowsFeature("microphone", "http://example.com"), "Microphone is enabled for example.com");
ok(document.policy.allowsFeature("microphone", "http://example.org"), "Microphone is enabled for example.org");
ok(document.policy.allowsFeature("microphone", "http://example.com"), "Microphone is allowed for example.com");
ok(document.policy.allowsFeature("microphone", "http://example.org"), "Microphone is allowed for example.org");
allowed = document.policy.getAllowlistForFeature("microphone");
is(allowed.length, 0, "No allowlist for microphone");
@ -68,15 +68,15 @@ function test_iframe_without_allow() {
ok(!ifr.policy.allowsFeature("foobar"), "Random feature");
ok(!ifr.policy.allowsFeature("foobar", "http://www.something.net"), "Random feature");
ok(ifr.policy.allowsFeature("camera"), "Camera is always allowed");
ok(ifr.policy.allowsFeature("camera", location.origin), "Camera is always allowed");
ok(ifr.policy.allowsFeature("camera", "http://foo.bar"), "Camera is always allowed");
ok(ifr.policy.allowsFeature("camera"), "Camera is allowed for self");
ok(ifr.policy.allowsFeature("camera", location.origin), "Camera is allowed for self");
ok(!ifr.policy.allowsFeature("camera", "http://foo.bar"), "Camera is not allowed for a random URL");
let allowed = ifr.policy.getAllowlistForFeature("camera");
is(allowed.length, 1, "Only 1 entry in allowlist for camera");
is(allowed[0], "*", "allowlist is '*'");
is(allowed[0], location.origin, "allowlist is 'self'");
ok(ifr.policy.allowsFeature("geolocation"), "Geolocation is enabled for all");
ok(ifr.policy.allowsFeature("geolocation", location.origin), "Geolocation is enabled for all");
ok(ifr.policy.allowsFeature("geolocation"), "Geolocation is allowed for all");
ok(ifr.policy.allowsFeature("geolocation", location.origin), "Geolocation is allowed for all");
ok(ifr.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is allowed for any random URL");
allowed = ifr.policy.getAllowlistForFeature("geolocation");
is(allowed.length, 1, "Only 1 entry in allowlist for geolocation");
@ -116,13 +116,13 @@ function test_iframe_with_allow() {
ok(!ifr.policy.allowsFeature("foobar"), "Random feature");
ok(!ifr.policy.allowsFeature("foobar", "http://www.something.net"), "Random feature");
ok(!ifr.policy.allowsFeature("camera"), "Camera is not enabled");
ok(!ifr.policy.allowsFeature("camera"), "Camera is not allowed");
let allowed = ifr.policy.getAllowlistForFeature("camera");
is(allowed.length, 0, "Camera has an empty allowlist");
ok(ifr.policy.allowsFeature("geolocation"), "Geolocation is enabled for all");
ok(ifr.policy.allowsFeature("geolocation", location.origin), "Geolocation is enabled for all");
ok(ifr.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is enabled for all");
ok(ifr.policy.allowsFeature("geolocation"), "Geolocation is allowed for all");
ok(ifr.policy.allowsFeature("geolocation", location.origin), "Geolocation is allowed for all");
ok(ifr.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is allowed for all");
allowed = ifr.policy.getAllowlistForFeature("geolocation");
is(allowed.length, 1, "Only 1 entry in allowlist for geolocation");
is(allowed[0], "*", "allowlist is '*'");
@ -157,15 +157,16 @@ function test_iframe_contentDocument() {
ok(!ifr.contentDocument.policy.allowsFeature("foobar"), "Random feature");
ok(!ifr.contentDocument.policy.allowsFeature("foobar", "http://www.something.net"), "Random feature");
ok(ifr.contentDocument.policy.allowsFeature("camera"), "Camera is always allowed");
ok(ifr.contentDocument.policy.allowsFeature("camera", "http://foo.bar"), "Camera is always allowed");
ok(ifr.contentDocument.policy.allowsFeature("camera"), "Camera is allowed for self");
ok(ifr.contentDocument.policy.allowsFeature("camera", location.origin), "Camera is allowed for self");
ok(!ifr.contentDocument.policy.allowsFeature("camera", "http://foo.bar"), "Camera is allowed for self");
let allowed = ifr.contentDocument.policy.getAllowlistForFeature("camera");
is(allowed.length, 1, "Only 1 entry in allowlist for camera");
is(allowed[0], "*", "allowlist is '*'");
is(allowed[0], location.origin, "allowlist is 'self'");
ok(ifr.contentDocument.policy.allowsFeature("geolocation"), "Geolocation is enabled for all");
ok(ifr.contentDocument.policy.allowsFeature("geolocation", location.origin), "Geolocation is enabled for all");
ok(ifr.contentDocument.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is enabled for any random URL");
ok(ifr.contentDocument.policy.allowsFeature("geolocation"), "Geolocation is allowed for all");
ok(ifr.contentDocument.policy.allowsFeature("geolocation", location.origin), "Geolocation is allowed for all");
ok(ifr.contentDocument.policy.allowsFeature("geolocation", "http://foo.bar"), "Geolocation is allowed for any random URL");
allowed = ifr.contentDocument.policy.getAllowlistForFeature("geolocation");
is(allowed.length, 1, "Only 1 entry in allowlist for geolocation");
is(allowed[0], "*", "allowlist is '*'");
@ -173,8 +174,8 @@ function test_iframe_contentDocument() {
ok(!ifr.contentDocument.policy.allowsFeature("microphone"), "Microphone is disabled for self");
ok(!ifr.contentDocument.policy.allowsFeature("microphone", location.origin), "Microphone is disabled for self");
ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://foo.bar"), "Microphone is disabled for foo.bar");
ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://example.com"), "Microphone is enabled for example.com");
ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://example.org"), "Microphone is enabled for example.org");
ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://example.com"), "Microphone is allowed for example.com");
ok(!ifr.contentDocument.policy.allowsFeature("microphone", "http://example.org"), "Microphone is allowed for example.org");
allowed = ifr.contentDocument.policy.getAllowlistForFeature("microphone");
is(allowed.length, 0, "No allowlist for microphone");

View File

@ -25,23 +25,10 @@ XULMenuElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return XULMenuElement_Binding::Wrap(aCx, this, aGivenProto);
}
nsIFrame*
XULMenuElement::GetFrame()
{
nsCOMPtr<nsIContent> kungFuDeathGrip = this; // keep a reference
nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
if (doc) {
doc->FlushPendingNotifications(FlushType::Frames);
}
return GetPrimaryFrame();
}
already_AddRefed<Element>
XULMenuElement::GetActiveChild()
{
nsMenuFrame* menu = do_QueryFrame(GetFrame());
nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (menu) {
RefPtr<Element> el;
menu->GetActiveChild(getter_AddRefs(el));
@ -53,7 +40,7 @@ XULMenuElement::GetActiveChild()
void
XULMenuElement::SetActiveChild(Element* arg)
{
nsMenuFrame* menu = do_QueryFrame(GetFrame());
nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (menu) {
menu->SetActiveChild(arg);
}
@ -75,7 +62,7 @@ XULMenuElement::HandleKeyPress(KeyboardEvent& keyEvent)
if (nsMenuBarListener::IsAccessKeyPressed(&keyEvent))
return false;
nsMenuFrame* menu = do_QueryFrame(GetFrame());
nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (!menu) {
return false;
}
@ -104,7 +91,7 @@ XULMenuElement::HandleKeyPress(KeyboardEvent& keyEvent)
bool
XULMenuElement::OpenedWithKey()
{
nsMenuFrame* menuframe = do_QueryFrame(GetFrame());
nsMenuFrame* menuframe = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (!menuframe) {
return false;
}

View File

@ -33,19 +33,6 @@ XULPopupElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
return XULPopupElement_Binding::Wrap(aCx, this, aGivenProto);
}
nsIFrame*
XULPopupElement::GetFrame(bool aFlushLayout)
{
nsCOMPtr<nsIContent> kungFuDeathGrip = this; // keep a reference
nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
if (doc) {
doc->FlushPendingNotifications(aFlushLayout ? FlushType::Layout : FlushType::Frames);
}
return GetPrimaryFrame();
}
void
XULPopupElement::OpenPopup(Element* aAnchorElement,
const StringOrOpenPopupOptions& aOptions,
@ -243,7 +230,7 @@ XULPopupElement::GetOuterScreenRect()
RefPtr<DOMRect> rect = new DOMRect(ToSupports(this));
// Return an empty rectangle if the popup is not open.
nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (!menuPopupFrame || !menuPopupFrame->IsOpen()) {
return rect.forget();
}
@ -267,7 +254,7 @@ XULPopupElement::GetAlignmentPosition(nsString& positionStr)
positionStr.Truncate();
// This needs to flush layout.
nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(true));
nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame(FlushType::Layout));
if (!menuPopupFrame)
return;
@ -315,7 +302,7 @@ XULPopupElement::GetAlignmentPosition(nsString& positionStr)
int32_t
XULPopupElement::AlignmentOffset()
{
nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (!menuPopupFrame)
return 0;
@ -331,7 +318,7 @@ XULPopupElement::AlignmentOffset()
void
XULPopupElement::SetConstraintRect(dom::DOMRectReadOnly& aRect)
{
nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
if (menuPopupFrame) {
menuPopupFrame->SetOverrideConstraintRect(
LayoutDeviceIntRect::Truncate(aRect.Left(), aRect.Top(), aRect.Width(), aRect.Height()));

View File

@ -528,10 +528,7 @@ nsXULElement::HasMenu()
void
nsXULElement::OpenMenu(bool aOpenFlag)
{
nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
if (doc) {
doc->FlushPendingNotifications(FlushType::Frames);
}
nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame(FlushType::Frames));
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (pm) {
@ -539,13 +536,10 @@ nsXULElement::OpenMenu(bool aOpenFlag)
// Nothing will happen if this element isn't a menu.
pm->ShowMenu(this, false, false);
}
else {
nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame());
if (menu) {
nsMenuPopupFrame* popupFrame = menu->GetPopup();
if (popupFrame) {
pm->HidePopup(popupFrame->GetContent(), false, true, false, false);
}
else if (menu) {
nsMenuPopupFrame* popupFrame = menu->GetPopup();
if (popupFrame) {
pm->HidePopup(popupFrame->GetContent(), false, true, false, false);
}
}
}

View File

@ -0,0 +1,24 @@
dbgGlobal = newGlobal();
dbg = new dbgGlobal.Debugger;
dbg.addDebuggee(this);
function f() {
dbg.getNewestFrame().older.eval("");
}
function execModule(source) {
m = parseModule(source);
m.declarationInstantiation();
m.evaluation();
}
execModule("f();");
gc();
let caught;
try {
execModule("throw 'foo'");
} catch (e) {
caught = e;
}
assertEq(caught, 'foo');

View File

@ -2807,10 +2807,11 @@ DebugEnvironments::takeFrameSnapshot(JSContext* cx, Handle<DebugEnvironmentProxy
* invariants since DebugEnvironmentProxy::maybeSnapshot can already be nullptr.
*/
JSScript* script = frame.script();
// Act like no snapshot was taken if we run OOM while taking the snapshot.
Rooted<GCVector<Value>> vec(cx, GCVector<Value>(cx));
if (debugEnv->environment().is<CallObject>()) {
JSScript* script = frame.script();
FunctionScope* scope = &script->bodyScope()->as<FunctionScope>();
uint32_t frameSlotCount = scope->nextFrameSlot();
@ -2848,7 +2849,7 @@ DebugEnvironments::takeFrameSnapshot(JSContext* cx, Handle<DebugEnvironmentProxy
LexicalScope* scope = &debugEnv->environment().as<LexicalEnvironmentObject>().scope();
frameSlotStart = scope->firstFrameSlot();
frameSlotEnd = scope->nextFrameSlot();
} else {
} else if (debugEnv->environment().is<VarEnvironmentObject>()) {
VarEnvironmentObject* env = &debugEnv->environment().as<VarEnvironmentObject>();
if (frame.isFunctionFrame()) {
VarScope* scope = &env->scope().as<VarScope>();
@ -2856,14 +2857,20 @@ DebugEnvironments::takeFrameSnapshot(JSContext* cx, Handle<DebugEnvironmentProxy
frameSlotEnd = scope->nextFrameSlot();
} else {
EvalScope* scope = &env->scope().as<EvalScope>();
MOZ_ASSERT(scope == frame.script()->bodyScope());
MOZ_ASSERT(scope == script->bodyScope());
frameSlotStart = 0;
frameSlotEnd = scope->nextFrameSlot();
}
} else {
MOZ_ASSERT(&debugEnv->environment().as<ModuleEnvironmentObject>() ==
script->module()->environment());
ModuleScope* scope = &script->bodyScope()->as<ModuleScope>();
frameSlotStart = 0;
frameSlotEnd = scope->nextFrameSlot();
}
uint32_t frameSlotCount = frameSlotEnd - frameSlotStart;
MOZ_ASSERT(frameSlotCount <= frame.script()->nfixed());
MOZ_ASSERT(frameSlotCount <= script->nfixed());
if (!vec.resize(frameSlotCount)) {
cx->recoverFromOutOfMemory();
@ -3022,6 +3029,12 @@ DebugEnvironments::onPopWith(AbstractFramePtr frame)
}
}
void
DebugEnvironments::onPopModule(JSContext* cx, const EnvironmentIter& ei)
{
onPopGeneric<ModuleEnvironmentObject, ModuleScope>(cx, ei);
}
void
DebugEnvironments::onRealmUnsetIsDebuggee(Realm* realm)
{

View File

@ -1054,6 +1054,7 @@ class DebugEnvironments
static void onPopLexical(JSContext* cx, const EnvironmentIter& ei);
static void onPopLexical(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc);
static void onPopWith(AbstractFramePtr frame);
static void onPopModule(JSContext* cx, const EnvironmentIter& ei);
static void onRealmUnsetIsDebuggee(Realm* realm);
};

View File

@ -1243,10 +1243,14 @@ PopEnvironment(JSContext* cx, EnvironmentIter& ei)
ei.initialFrame().popOffEnvironmentChain<VarEnvironmentObject>();
}
break;
case ScopeKind::Module:
if (MOZ_UNLIKELY(cx->realm()->isDebuggee())) {
DebugEnvironments::onPopModule(cx, ei);
}
break;
case ScopeKind::Eval:
case ScopeKind::Global:
case ScopeKind::NonSyntactic:
case ScopeKind::Module:
break;
case ScopeKind::WasmInstance:
case ScopeKind::WasmFunction:

View File

@ -17,6 +17,7 @@ NS_IMPL_RELEASE(PartiallySeekableInputStream);
NS_INTERFACE_MAP_BEGIN(PartiallySeekableInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
NS_INTERFACE_MAP_ENTRY(nsITellableStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
mWeakCloneableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,

View File

@ -34,6 +34,7 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM

View File

@ -26,6 +26,7 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIASYNCINPUTSTREAM
void AllowInput();
@ -42,7 +43,8 @@ private:
nsCOMPtr<nsIEventTarget> mEventTarget;
};
NS_IMPL_ISUPPORTS(ThrottleInputStream, nsIAsyncInputStream, nsIInputStream, nsISeekableStream)
NS_IMPL_ISUPPORTS(ThrottleInputStream, nsIAsyncInputStream, nsIInputStream,
nsITellableStream, nsISeekableStream)
ThrottleInputStream::ThrottleInputStream(nsIInputStream *aStream, ThrottleQueue* aQueue)
: mStream(aStream)
@ -160,7 +162,7 @@ ThrottleInputStream::Tell(int64_t* aResult)
return mClosedStatus;
}
nsCOMPtr<nsISeekableStream> sstream = do_QueryInterface(mStream);
nsCOMPtr<nsITellableStream> sstream = do_QueryInterface(mStream);
if (!sstream) {
return NS_ERROR_FAILURE;
}

View File

@ -63,7 +63,7 @@ nsBufferedStream::~nsBufferedStream()
Close();
}
NS_IMPL_ISUPPORTS(nsBufferedStream, nsISeekableStream)
NS_IMPL_ISUPPORTS(nsBufferedStream, nsITellableStream, nsISeekableStream)
nsresult
nsBufferedStream::Init(nsISupports* stream, uint32_t bufferSize)
@ -305,6 +305,7 @@ NS_IMPL_CI_INTERFACE_GETTER(nsBufferedInputStream,
nsIInputStream,
nsIBufferedInputStream,
nsISeekableStream,
nsITellableStream,
nsIStreamBufferAccess)
nsBufferedInputStream::nsBufferedInputStream()

View File

@ -26,6 +26,7 @@ class nsBufferedStream : public nsISeekableStream
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
nsBufferedStream();

View File

@ -61,6 +61,7 @@ nsFileStreamBase::~nsFileStreamBase()
NS_IMPL_ISUPPORTS(nsFileStreamBase,
nsISeekableStream,
nsITellableStream,
nsIFileMetadata)
NS_IMETHODIMP
@ -442,6 +443,7 @@ NS_IMPL_CI_INTERFACE_GETTER(nsFileInputStream,
nsIInputStream,
nsIFileInputStream,
nsISeekableStream,
nsITellableStream,
nsILineInputStream)
nsresult

View File

@ -31,6 +31,7 @@ public:
// consistent threads when recording/replaying.
NS_DECL_THREADSAFE_ISUPPORTS_WITH_RECORDING(mozilla::recordreplay::Behavior::Preserve)
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIFILEMETADATA
nsFileStreamBase();

View File

@ -574,10 +574,10 @@ nsInputStreamPump::OnStateTransfer()
// such an error. (see bug 189672)
// in most cases this QI will succeed (mAsyncStream is almost always
// a nsPipeInputStream, which implements nsISeekableStream::Tell).
// a nsPipeInputStream, which implements nsITellableStream::Tell).
int64_t offsetBefore;
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mAsyncStream);
if (seekable && NS_FAILED(seekable->Tell(&offsetBefore))) {
nsCOMPtr<nsITellableStream> tellable = do_QueryInterface(mAsyncStream);
if (tellable && NS_FAILED(tellable->Tell(&offsetBefore))) {
MOZ_ASSERT_UNREACHABLE("Tell failed on readable stream");
offsetBefore = 0;
}
@ -602,11 +602,11 @@ nsInputStreamPump::OnStateTransfer()
// don't enter this code if ODA failed or called Cancel
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(mStatus)) {
// test to see if this ODA failed to consume data
if (seekable) {
if (tellable) {
// NOTE: if Tell fails, which can happen if the stream is
// now closed, then we assume that everything was read.
int64_t offsetAfter;
if (NS_FAILED(seekable->Tell(&offsetAfter)))
if (NS_FAILED(tellable->Tell(&offsetAfter)))
offsetAfter = offsetBefore + odaAvail;
if (offsetAfter > offsetBefore)
mStreamOffset += (offsetAfter - offsetBefore);

View File

@ -47,6 +47,7 @@ public:
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIMIMEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
@ -98,6 +99,7 @@ NS_INTERFACE_MAP_BEGIN(nsMIMEInputStream)
NS_INTERFACE_MAP_ENTRY(nsIMIMEInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIInputStream, nsIMIMEInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
NS_INTERFACE_MAP_ENTRY(nsITellableStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
IsIPCSerializable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
@ -120,7 +122,8 @@ NS_IMPL_CI_INTERFACE_GETTER(nsMIMEInputStream,
nsIMIMEInputStream,
nsIAsyncInputStream,
nsIInputStream,
nsISeekableStream)
nsISeekableStream,
nsITellableStream)
nsMIMEInputStream::nsMIMEInputStream()
: mStartedReading(false)
@ -312,13 +315,15 @@ nsMIMEInputStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
return callback->OnInputStreamReady(this);
}
// nsISeekableStream
// nsITellableStream
NS_IMETHODIMP nsMIMEInputStream::Tell(int64_t *_retval)
{
INITSTREAMS;
nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStream);
nsCOMPtr<nsITellableStream> stream = do_QueryInterface(mStream);
return stream->Tell(_retval);
}
// nsISeekableStream
NS_IMETHODIMP nsMIMEInputStream::SetEOF(void) {
INITSTREAMS;
nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStream);

View File

@ -38,6 +38,7 @@ NS_INTERFACE_MAP_BEGIN(CacheFileInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
NS_INTERFACE_MAP_ENTRY(nsITellableStream)
NS_INTERFACE_MAP_ENTRY(mozilla::net::CacheFileChunkListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
@ -388,6 +389,14 @@ CacheFileInputStream::Seek(int32_t whence, int64_t offset)
return NS_OK;
}
NS_IMETHODIMP
CacheFileInputStream::SetEOF()
{
MOZ_ASSERT(false, "Don't call SetEOF on cache input stream");
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsITellableStream
NS_IMETHODIMP
CacheFileInputStream::Tell(int64_t *_retval)
{
@ -408,13 +417,6 @@ CacheFileInputStream::Tell(int64_t *_retval)
return NS_OK;
}
NS_IMETHODIMP
CacheFileInputStream::SetEOF()
{
MOZ_ASSERT(false, "Don't call SetEOF on cache input stream");
return NS_ERROR_NOT_IMPLEMENTED;
}
// CacheFileChunkListener
nsresult
CacheFileInputStream::OnChunkRead(nsresult aResult, CacheFileChunk *aChunk)

View File

@ -24,6 +24,7 @@ class CacheFileInputStream : public nsIAsyncInputStream
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
public:
explicit CacheFileInputStream(CacheFile *aFile, nsISupports *aEntry,

View File

@ -40,6 +40,7 @@ NS_INTERFACE_MAP_BEGIN(CacheFileOutputStream)
NS_INTERFACE_MAP_ENTRY(nsIOutputStream)
NS_INTERFACE_MAP_ENTRY(nsIAsyncOutputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
NS_INTERFACE_MAP_ENTRY(nsITellableStream)
NS_INTERFACE_MAP_ENTRY(mozilla::net::CacheFileChunkListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIOutputStream)
NS_INTERFACE_MAP_END
@ -288,6 +289,17 @@ CacheFileOutputStream::Seek(int32_t whence, int64_t offset)
return NS_OK;
}
NS_IMETHODIMP
CacheFileOutputStream::SetEOF()
{
MOZ_ASSERT(false, "CacheFileOutputStream::SetEOF() not implemented");
// Right now we don't use SetEOF(). If we ever need this method, we need
// to think about what to do with input streams that already points beyond
// new EOF.
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsITellableStream
NS_IMETHODIMP
CacheFileOutputStream::Tell(int64_t *_retval)
{
@ -308,16 +320,6 @@ CacheFileOutputStream::Tell(int64_t *_retval)
return NS_OK;
}
NS_IMETHODIMP
CacheFileOutputStream::SetEOF()
{
MOZ_ASSERT(false, "CacheFileOutputStream::SetEOF() not implemented");
// Right now we don't use SetEOF(). If we ever need this method, we need
// to think about what to do with input streams that already points beyond
// new EOF.
return NS_ERROR_NOT_IMPLEMENTED;
}
// CacheFileChunkListener
nsresult
CacheFileOutputStream::OnChunkRead(nsresult aResult, CacheFileChunk *aChunk)

View File

@ -26,6 +26,7 @@ class CacheFileOutputStream : public nsIAsyncOutputStream
NS_DECL_NSIOUTPUTSTREAM
NS_DECL_NSIASYNCOUTPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
public:
CacheFileOutputStream(CacheFile *aFile,

View File

@ -920,14 +920,10 @@ HttpBaseChannel::EnsureUploadStreamIsCloneable(nsIRunnable* aCallback)
return NS_OK;
}
// Some nsSeekableStreams do not implement ::Seek() (see nsPipeInputStream).
// In this case, we must clone the uploadStream into a memory stream in order
// to have it seekable. If the CloneUploadStream() will succeed, then
// synchronously invoke the callback to indicate we're already cloneable.
// Upload nsIInputStream must be cloneable and seekable in order to be
// processed by devtools network inspector.
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
if (seekable &&
NS_SUCCEEDED(seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0)) &&
NS_InputStreamIsCloneable(mUploadStream)) {
if (seekable && NS_InputStreamIsCloneable(mUploadStream)) {
aCallback->Run();
return NS_OK;
}

View File

@ -0,0 +1,3 @@
[at-supports-040.html]
type: reftest
prefs: [layout.css.supports-selector.enabled:true]

View File

@ -0,0 +1,3 @@
[at-supports-041.html]
type: reftest
prefs: [layout.css.supports-selector.enabled:true]

View File

@ -0,0 +1,3 @@
[at-supports-042.html]
type: reftest
prefs: [layout.css.supports-selector.enabled:true]

View File

@ -0,0 +1,2 @@
[CSS.html]
prefs: [layout.css.supports-selector.enabled:true]

View File

@ -24,6 +24,8 @@ NS_INTERFACE_MAP_BEGIN(InputStreamLengthWrapper)
mWeakIPCSerializableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream,
mWeakSeekableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream,
mWeakTellableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
mWeakAsyncInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
@ -63,6 +65,7 @@ InputStreamLengthWrapper::InputStreamLengthWrapper(already_AddRefed<nsIInputStre
: mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
, mWeakTellableInputStream(nullptr)
, mWeakAsyncInputStream(nullptr)
, mLength(aLength)
, mConsumed(false)
@ -78,6 +81,7 @@ InputStreamLengthWrapper::InputStreamLengthWrapper()
: mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
, mWeakTellableInputStream(nullptr)
, mWeakAsyncInputStream(nullptr)
, mLength(-1)
, mConsumed(false)
@ -112,6 +116,12 @@ InputStreamLengthWrapper::SetSourceStream(already_AddRefed<nsIInputStream> aInpu
mWeakSeekableInputStream = seekableStream;
}
nsCOMPtr<nsITellableStream> tellableStream =
do_QueryInterface(mInputStream);
if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) {
mWeakTellableInputStream = tellableStream;
}
nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
do_QueryInterface(mInputStream);
if (asyncInputStream && SameCOMIdentity(mInputStream, asyncInputStream)) {
@ -330,15 +340,6 @@ InputStreamLengthWrapper::Seek(int32_t aWhence, int64_t aOffset)
return mWeakSeekableInputStream->Seek(aWhence, aOffset);
}
NS_IMETHODIMP
InputStreamLengthWrapper::Tell(int64_t *aResult)
{
NS_ENSURE_STATE(mInputStream);
NS_ENSURE_STATE(mWeakSeekableInputStream);
return mWeakSeekableInputStream->Tell(aResult);
}
NS_IMETHODIMP
InputStreamLengthWrapper::SetEOF()
{
@ -349,6 +350,17 @@ InputStreamLengthWrapper::SetEOF()
return mWeakSeekableInputStream->SetEOF();
}
// nsITellableStream
NS_IMETHODIMP
InputStreamLengthWrapper::Tell(int64_t *aResult)
{
NS_ENSURE_STATE(mInputStream);
NS_ENSURE_STATE(mWeakTellableInputStream);
return mWeakTellableInputStream->Tell(aResult);
}
// nsIInputStreamLength
NS_IMETHODIMP

View File

@ -36,6 +36,7 @@ public:
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIINPUTSTREAMLENGTH
@ -69,6 +70,7 @@ private:
nsICloneableInputStream* mWeakCloneableInputStream;
nsIIPCSerializableInputStream* mWeakIPCSerializableInputStream;
nsISeekableStream* mWeakSeekableInputStream;
nsITellableStream* mWeakTellableInputStream;
nsIAsyncInputStream* mWeakAsyncInputStream;
int64_t mLength;

View File

@ -51,6 +51,8 @@ NS_INTERFACE_MAP_BEGIN(NonBlockingAsyncInputStream)
mWeakIPCSerializableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream,
mWeakSeekableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream,
mWeakTellableInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
@ -88,6 +90,7 @@ NonBlockingAsyncInputStream::NonBlockingAsyncInputStream(already_AddRefed<nsIInp
, mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
, mWeakTellableInputStream(nullptr)
, mLock("NonBlockingAsyncInputStream::mLock")
, mClosed(false)
{
@ -111,6 +114,12 @@ NonBlockingAsyncInputStream::NonBlockingAsyncInputStream(already_AddRefed<nsIInp
if (seekableStream && SameCOMIdentity(mInputStream, seekableStream)) {
mWeakSeekableInputStream = seekableStream;
}
nsCOMPtr<nsITellableStream> tellableStream =
do_QueryInterface(mInputStream);
if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) {
mWeakTellableInputStream = tellableStream;
}
}
NonBlockingAsyncInputStream::~NonBlockingAsyncInputStream()
@ -350,13 +359,6 @@ NonBlockingAsyncInputStream::Seek(int32_t aWhence, int64_t aOffset)
return mWeakSeekableInputStream->Seek(aWhence, aOffset);
}
NS_IMETHODIMP
NonBlockingAsyncInputStream::Tell(int64_t* aResult)
{
NS_ENSURE_STATE(mWeakSeekableInputStream);
return mWeakSeekableInputStream->Tell(aResult);
}
NS_IMETHODIMP
NonBlockingAsyncInputStream::SetEOF()
{
@ -364,6 +366,15 @@ NonBlockingAsyncInputStream::SetEOF()
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsITellableStream
NS_IMETHODIMP
NonBlockingAsyncInputStream::Tell(int64_t* aResult)
{
NS_ENSURE_STATE(mWeakTellableInputStream);
return mWeakTellableInputStream->Tell(aResult);
}
void
NonBlockingAsyncInputStream::RunAsyncWaitCallback(NonBlockingAsyncInputStream::AsyncWaitRunnable* aRunnable,
already_AddRefed<nsIInputStreamCallback> aCallback)

View File

@ -34,6 +34,7 @@ public:
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
// |aInputStream| must be a non-blocking, non-async inputSteam.
static nsresult
@ -56,6 +57,7 @@ private:
nsICloneableInputStream* MOZ_NON_OWNING_REF mWeakCloneableInputStream;
nsIIPCSerializableInputStream* MOZ_NON_OWNING_REF mWeakIPCSerializableInputStream;
nsISeekableStream* MOZ_NON_OWNING_REF mWeakSeekableInputStream;
nsITellableStream* MOZ_NON_OWNING_REF mWeakTellableInputStream;
Mutex mLock;

View File

@ -26,6 +26,8 @@ NS_INTERFACE_MAP_BEGIN(SlicedInputStream)
mWeakIPCSerializableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream,
mWeakSeekableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream,
mWeakTellableInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
mWeakAsyncInputStream || !mInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
@ -44,6 +46,7 @@ SlicedInputStream::SlicedInputStream(already_AddRefed<nsIInputStream> aInputStre
: mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
, mWeakTellableInputStream(nullptr)
, mWeakAsyncInputStream(nullptr)
, mWeakInputStreamLength(nullptr)
, mWeakAsyncInputStreamLength(nullptr)
@ -63,6 +66,7 @@ SlicedInputStream::SlicedInputStream()
: mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakSeekableInputStream(nullptr)
, mWeakTellableInputStream(nullptr)
, mWeakAsyncInputStream(nullptr)
, mStart(0)
, mLength(0)
@ -102,6 +106,12 @@ SlicedInputStream::SetSourceStream(already_AddRefed<nsIInputStream> aInputStream
mWeakSeekableInputStream = seekableStream;
}
nsCOMPtr<nsITellableStream> tellableStream =
do_QueryInterface(mInputStream);
if (tellableStream && SameCOMIdentity(mInputStream, tellableStream)) {
mWeakTellableInputStream = tellableStream;
}
nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
do_QueryInterface(mInputStream);
if (asyncInputStream && SameCOMIdentity(mInputStream, asyncInputStream)) {
@ -544,14 +554,26 @@ SlicedInputStream::Seek(int32_t aWhence, int64_t aOffset)
}
NS_IMETHODIMP
SlicedInputStream::Tell(int64_t *aResult)
SlicedInputStream::SetEOF()
{
NS_ENSURE_STATE(mInputStream);
NS_ENSURE_STATE(mWeakSeekableInputStream);
mClosed = true;
return mWeakSeekableInputStream->SetEOF();
}
// nsITellableStream
NS_IMETHODIMP
SlicedInputStream::Tell(int64_t *aResult)
{
NS_ENSURE_STATE(mInputStream);
NS_ENSURE_STATE(mWeakTellableInputStream);
int64_t tell = 0;
nsresult rv = mWeakSeekableInputStream->Tell(&tell);
nsresult rv = mWeakTellableInputStream->Tell(&tell);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -569,16 +591,6 @@ SlicedInputStream::Tell(int64_t *aResult)
return NS_OK;
}
NS_IMETHODIMP
SlicedInputStream::SetEOF()
{
NS_ENSURE_STATE(mInputStream);
NS_ENSURE_STATE(mWeakSeekableInputStream);
mClosed = true;
return mWeakSeekableInputStream->SetEOF();
}
// nsIInputStreamLength
NS_IMETHODIMP

View File

@ -36,6 +36,7 @@ public:
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIINPUTSTREAMLENGTH
NS_DECL_NSIASYNCINPUTSTREAMLENGTH
@ -73,6 +74,7 @@ private:
nsICloneableInputStream* mWeakCloneableInputStream;
nsIIPCSerializableInputStream* mWeakIPCSerializableInputStream;
nsISeekableStream* mWeakSeekableInputStream;
nsITellableStream* mWeakTellableInputStream;
nsIAsyncInputStream* mWeakAsyncInputStream;
nsIInputStreamLength* mWeakInputStreamLength;
nsIAsyncInputStreamLength* mWeakAsyncInputStreamLength;

View File

@ -33,6 +33,7 @@ XPIDL_SOURCES += [
'nsIStorageStream.idl',
'nsIStreamBufferAccess.idl',
'nsIStringStream.idl',
'nsITellableStream.idl',
'nsIUnicharInputStream.idl',
'nsIUnicharLineInputStream.idl',
'nsIUnicharOutputStream.idl',

View File

@ -4,6 +4,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsITellableStream.idl"
/*
* nsISeekableStream
*
@ -14,7 +16,7 @@
#include "nsISupports.idl"
[scriptable, uuid(8429d350-1040-4661-8b71-f2a6ba455980)]
interface nsISeekableStream : nsISupports
interface nsISeekableStream : nsITellableStream
{
/*
* Sets the stream pointer to the value of the 'offset' parameter
@ -52,17 +54,6 @@ interface nsISeekableStream : nsISupports
*/
void seek(in long whence, in long long offset);
/**
* tell
*
* This method reports the current offset, in bytes, from the start of the
* stream.
*
* @throws NS_BASE_STREAM_CLOSED if called on a closed stream.
*/
long long tell();
/**
* setEOF
*

View File

@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
/*
* nsITellableStream
*
* This class is separate from nsISeekableStream in order to let streams to
* implement ::Tell() without implementing the whole nsISeekableStream
* interface. Callers can QI the stream to know what is implemented. This is
* mainly done for nsPipeInputStream.
*
*
* Implementing this interface, streams are able to expose the current offset
* via ::tell().
*/
#include "nsISupports.idl"
[scriptable, uuid(ee942946-4538-45d2-bf05-ffdbf5932621)]
interface nsITellableStream : nsISupports
{
/**
* tell
*
* This method reports the current offset, in bytes, from the start of the
* stream.
*
* @throws NS_BASE_STREAM_CLOSED if called on a closed stream.
*/
long long tell();
};

View File

@ -56,6 +56,7 @@ public:
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIMULTIPLEXINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
@ -77,6 +78,7 @@ public:
mStream = aStream;
mAsyncStream = do_QueryInterface(aStream);
mSeekableStream = do_QueryInterface(aStream);
mTellableStream = do_QueryInterface(aStream);
mBuffered = aBuffered;
}
@ -86,6 +88,8 @@ public:
nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
// This can be null.
nsCOMPtr<nsISeekableStream> mSeekableStream;
// This can be null.
nsCOMPtr<nsITellableStream> mTellableStream;
// True if the stream is wrapped with nsIBufferedInputStream.
bool mBuffered;
@ -104,8 +108,8 @@ private:
nsresult
AsyncWaitInternal();
// This method updates mSeekableStreams, mIPCSerializableStreams,
// mCloneableStreams and mAsyncInputStreams values.
// This method updates mSeekableStreams, mTellableStreams,
// mIPCSerializableStreams, mCloneableStreams and mAsyncInputStreams values.
void UpdateQIMap(StreamData& aStream, int32_t aCount);
struct MOZ_STACK_CLASS ReadSegmentsState
@ -122,6 +126,7 @@ private:
uint32_t aCount, uint32_t* aWriteCount);
bool IsSeekable() const;
bool IsTellable() const;
bool IsIPCSerializable() const;
bool IsCloneable() const;
bool IsAsyncInputStream() const;
@ -145,6 +150,7 @@ private:
RefPtr<AsyncWaitLengthHelper> mAsyncWaitLengthHelper;
uint32_t mSeekableStreams;
uint32_t mTellableStreams;
uint32_t mIPCSerializableStreams;
uint32_t mCloneableStreams;
uint32_t mAsyncInputStreams;
@ -162,6 +168,7 @@ NS_INTERFACE_MAP_BEGIN(nsMultiplexInputStream)
NS_INTERFACE_MAP_ENTRY(nsIMultiplexInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream, IsTellable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
IsIPCSerializable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
@ -181,7 +188,8 @@ NS_INTERFACE_MAP_END
NS_IMPL_CI_INTERFACE_GETTER(nsMultiplexInputStream,
nsIMultiplexInputStream,
nsIInputStream,
nsISeekableStream)
nsISeekableStream,
nsITellableStream)
static nsresult
AvailableMaybeSeek(nsMultiplexInputStream::StreamData& aStream,
@ -205,17 +213,18 @@ AvailableMaybeSeek(nsMultiplexInputStream::StreamData& aStream,
}
static nsresult
TellMaybeSeek(nsISeekableStream* aSeekable, int64_t* aResult)
TellMaybeSeek(nsITellableStream* aTellable, nsISeekableStream* aSeekable,
int64_t* aResult)
{
nsresult rv = aSeekable->Tell(aResult);
if (rv == NS_BASE_STREAM_CLOSED) {
nsresult rv = aTellable->Tell(aResult);
if (rv == NS_BASE_STREAM_CLOSED && aSeekable) {
// Blindly seek to the current position if Tell() returns
// NS_BASE_STREAM_CLOSED.
// If nsIFileInputStream is closed in Read() due to CLOSE_ON_EOF flag,
// Seek() could reopen the file if REOPEN_ON_REWIND flag is set.
nsresult rvSeek = aSeekable->Seek(nsISeekableStream::NS_SEEK_CUR, 0);
if (NS_SUCCEEDED(rvSeek)) {
rv = aSeekable->Tell(aResult);
rv = aTellable->Tell(aResult);
}
}
return rv;
@ -229,6 +238,7 @@ nsMultiplexInputStream::nsMultiplexInputStream()
, mAsyncWaitFlags(0)
, mAsyncWaitRequestedCount(0)
, mSeekableStreams(0)
, mTellableStreams(0)
, mIPCSerializableStreams(0)
, mCloneableStreams(0)
, mAsyncInputStreams(0)
@ -579,6 +589,8 @@ nsMultiplexInputStream::Seek(int32_t aWhence, int64_t aOffset)
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(mStreams[i].mTellableStream);
// See if all remaining streams should be rewound
if (remaining == 0) {
if (i < oldCurrentStream ||
@ -599,7 +611,7 @@ nsMultiplexInputStream::Seek(int32_t aWhence, int64_t aOffset)
(i == oldCurrentStream && !oldStartedReadingCurrent)) {
streamPos = 0;
} else {
rv = TellMaybeSeek(stream, &streamPos);
rv = TellMaybeSeek(mStreams[i].mTellableStream, stream, &streamPos);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -682,7 +694,8 @@ nsMultiplexInputStream::Seek(int32_t aWhence, int64_t aOffset)
int64_t remaining = -aOffset;
for (uint32_t i = mCurrentStream; remaining && i != (uint32_t)-1; --i) {
int64_t pos;
rv = TellMaybeSeek(mStreams[i].mSeekableStream, &pos);
rv = TellMaybeSeek(mStreams[i].mTellableStream,
mStreams[i].mSeekableStream, &pos);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -761,7 +774,7 @@ nsMultiplexInputStream::Seek(int32_t aWhence, int64_t aOffset)
remaining += streamPos;
} else {
int64_t avail;
rv = TellMaybeSeek(stream, &avail);
rv = TellMaybeSeek(mStreams[i].mTellableStream, stream, &avail);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -805,12 +818,13 @@ nsMultiplexInputStream::Tell(int64_t* aResult)
uint32_t i, last;
last = mStartedReadingCurrent ? mCurrentStream + 1 : mCurrentStream;
for (i = 0; i < last; ++i) {
if (NS_WARN_IF(!mStreams[i].mSeekableStream)) {
if (NS_WARN_IF(!mStreams[i].mTellableStream)) {
return NS_ERROR_NO_INTERFACE;
}
int64_t pos;
rv = TellMaybeSeek(mStreams[i].mSeekableStream, &pos);
rv = TellMaybeSeek(mStreams[i].mTellableStream, mStreams[i].mSeekableStream,
&pos);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1515,6 +1529,7 @@ nsMultiplexInputStream::UpdateQIMap(StreamData& aStream, int32_t aCount)
MOZ_ASSERT(aCount == -1 || aCount == 1);
MAYBE_UPDATE_VALUE_REAL(mSeekableStreams, aStream.mSeekableStream)
MAYBE_UPDATE_VALUE_REAL(mTellableStreams, aStream.mTellableStream)
MAYBE_UPDATE_VALUE(mIPCSerializableStreams, nsIIPCSerializableInputStream)
MAYBE_UPDATE_VALUE(mCloneableStreams, nsICloneableInputStream)
MAYBE_UPDATE_VALUE_REAL(mAsyncInputStreams, aStream.mAsyncStream)
@ -1530,6 +1545,12 @@ nsMultiplexInputStream::IsSeekable() const
return mStreams.Length() == mSeekableStreams;
}
bool
nsMultiplexInputStream::IsTellable() const
{
return mStreams.Length() == mTellableStreams;
}
bool
nsMultiplexInputStream::IsIPCSerializable() const
{

View File

@ -12,7 +12,7 @@
#include "nsICloneableInputStream.h"
#include "nsIPipe.h"
#include "nsIEventTarget.h"
#include "nsISeekableStream.h"
#include "nsITellableStream.h"
#include "mozilla/RefPtr.h"
#include "nsSegmentedBuffer.h"
#include "nsStreamUtils.h"
@ -142,7 +142,7 @@ struct nsPipeReadState
// an input end of a pipe (maintained as a list of refs within the pipe)
class nsPipeInputStream final
: public nsIAsyncInputStream
, public nsISeekableStream
, public nsITellableStream
, public nsISearchableInputStream
, public nsICloneableInputStream
, public nsIClassInfo
@ -155,7 +155,7 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS_WITH_RECORDING(recordreplay::Behavior::Preserve)
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSISEARCHABLEINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSICLASSINFO
@ -1250,7 +1250,7 @@ NS_IMPL_RELEASE(nsPipeInputStream);
NS_INTERFACE_TABLE_HEAD(nsPipeInputStream)
NS_INTERFACE_TABLE_BEGIN
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsIAsyncInputStream)
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsISeekableStream)
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsITellableStream)
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsISearchableInputStream)
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsICloneableInputStream)
NS_INTERFACE_TABLE_ENTRY(nsPipeInputStream, nsIBufferedInputStream)
@ -1265,7 +1265,7 @@ NS_INTERFACE_TABLE_TAIL
NS_IMPL_CI_INTERFACE_GETTER(nsPipeInputStream,
nsIInputStream,
nsIAsyncInputStream,
nsISeekableStream,
nsITellableStream,
nsISearchableInputStream,
nsICloneableInputStream,
nsIBufferedInputStream)
@ -1525,12 +1525,6 @@ nsPipeInputStream::AsyncWait(nsIInputStreamCallback* aCallback,
return NS_OK;
}
NS_IMETHODIMP
nsPipeInputStream::Seek(int32_t aWhence, int64_t aOffset)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsPipeInputStream::Tell(int64_t* aOffset)
{
@ -1545,13 +1539,6 @@ nsPipeInputStream::Tell(int64_t* aOffset)
return NS_OK;
}
NS_IMETHODIMP
nsPipeInputStream::SetEOF()
{
MOZ_ASSERT_UNREACHABLE("nsPipeInputStream::SetEOF");
return NS_ERROR_NOT_IMPLEMENTED;
}
static bool strings_equal(bool aIgnoreCase,
const char* aS1, const char* aS2, uint32_t aLen)
{

View File

@ -349,6 +349,7 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
@ -384,6 +385,7 @@ private:
NS_IMPL_ISUPPORTS(nsStorageInputStream,
nsIInputStream,
nsISeekableStream,
nsITellableStream,
nsIIPCSerializableInputStream,
nsICloneableInputStream)

View File

@ -44,6 +44,7 @@ public:
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISTRINGINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSITELLABLESTREAM
NS_DECL_NSISUPPORTSPRIMITIVE
NS_DECL_NSISUPPORTSCSTRING
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
@ -109,6 +110,7 @@ NS_IMPL_QUERY_INTERFACE_CI(nsStringInputStream,
nsIInputStream,
nsISupportsCString,
nsISeekableStream,
nsITellableStream,
nsIIPCSerializableInputStream,
nsICloneableInputStream)
NS_IMPL_CI_INTERFACE_GETTER(nsStringInputStream,
@ -116,6 +118,7 @@ NS_IMPL_CI_INTERFACE_GETTER(nsStringInputStream,
nsIInputStream,
nsISupportsCString,
nsISeekableStream,
nsITellableStream,
nsICloneableInputStream)
/////////
@ -322,17 +325,6 @@ nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset)
return NS_OK;
}
NS_IMETHODIMP
nsStringInputStream::Tell(int64_t* aOutWhere)
{
if (Closed()) {
return NS_BASE_STREAM_CLOSED;
}
*aOutWhere = mOffset;
return NS_OK;
}
NS_IMETHODIMP
nsStringInputStream::SetEOF()
{
@ -344,6 +336,21 @@ nsStringInputStream::SetEOF()
return NS_OK;
}
/////////
// nsITellableStream implementation
/////////
NS_IMETHODIMP
nsStringInputStream::Tell(int64_t* aOutWhere)
{
if (Closed()) {
return NS_BASE_STREAM_CLOSED;
}
*aOutWhere = mOffset;
return NS_OK;
}
/////////
// nsIIPCSerializableInputStream implementation
/////////

View File

@ -16,6 +16,7 @@
* nsIStringInputStream
* nsIInputStream
* nsISeekableStream
* nsITellableStream
* nsISupportsCString
*/
#define NS_STRINGINPUTSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1"
@ -29,7 +30,7 @@
/**
* Factory method to get an nsInputStream from a byte buffer. Result will
* implement nsIStringInputStream and nsISeekableStream.
* implement nsIStringInputStream, nsITellableStream and nsISeekableStream.
*
* If aAssignment is NS_ASSIGNMENT_COPY, then the resulting stream holds a copy
* of the given buffer (aStringToRead), and the caller is free to discard
@ -54,7 +55,7 @@ NS_NewByteInputStream(nsIInputStream** aStreamResult,
/**
* Factory method to get an nsInputStream from an nsACString. Result will
* implement nsIStringInputStream and nsISeekableStream.
* implement nsIStringInputStream, nsTellableStream and nsISeekableStream.
*/
extern nsresult
NS_NewCStringInputStream(nsIInputStream** aStreamResult,

View File

@ -19,7 +19,7 @@
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIPipe.h"
#include "nsISeekableStream.h"
#include "nsITellableStream.h"
#include "nsIThread.h"
#include "nsIRunnable.h"
#include "nsStreamUtils.h"
@ -1078,7 +1078,7 @@ TEST(Pipes, Interfaces)
nsCOMPtr<nsIAsyncInputStream> readerType1 = do_QueryInterface(reader);
ASSERT_TRUE(readerType1);
nsCOMPtr<nsISeekableStream> readerType2 = do_QueryInterface(reader);
nsCOMPtr<nsITellableStream> readerType2 = do_QueryInterface(reader);
ASSERT_TRUE(readerType2);
nsCOMPtr<nsISearchableInputStream> readerType3 = do_QueryInterface(reader);