Backed out 2 changesets (bug 1487113) for mochitest failure at dom/base/test/test_script_loader_js_cache.html.

Backed out changeset dce59b615568 (bug 1487113)
Backed out changeset e6f579752678 (bug 1487113)
This commit is contained in:
Daniel Varga 2019-05-20 21:04:40 +03:00
parent 636c68369c
commit 9054636e2c
11 changed files with 199 additions and 126 deletions

View File

@ -140,16 +140,18 @@ interface nsICacheInfoChannel : nsISupports
/**
* If preferAlternativeDataType() has been called passing deliverAltData
* equal to false, this attribute will expose the alt-data inputStream if
* avaiable.
* equal to false, this method will expose the alt-data inputStream if
* aviable.
*/
readonly attribute nsIInputStream alternativeDataInputStream;
void getAltDataInputStream(in ACString type,
in nsIInputStreamReceiver aReceiver);
/**
* Sometimes when the channel is delivering alt-data, we may want to somehow
* access the original content too.
* access the original content too. This method asynchronously opens the
* input stream and delivers it to the receiver.
*/
readonly attribute nsIInputStream originalInputStream;
void getOriginalInputStream(in nsIInputStreamReceiver aReceiver);
/**
* Opens and returns an output stream that a consumer may use to save an

View File

@ -395,25 +395,20 @@ void HttpChannelChild::AssociateApplicationCache(const nsCString& groupID,
class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
public:
StartRequestEvent(HttpChannelChild* aChild, const nsresult& aChannelStatus,
const nsHttpResponseHead& aResponseHead,
const bool& aUseResponseHead,
const nsHttpHeaderArray& aRequestHeaders,
const ParentLoadInfoForwarderArgs& loadInfoForwarder,
const bool& aIsFromCache, const bool& aIsRacing,
const bool& aCacheEntryAvailable,
const uint64_t& aCacheEntryId,
const int32_t& aCacheFetchCount,
const uint32_t& aCacheExpirationTime,
const nsCString& aCachedCharset,
const nsCString& aSecurityInfoSerialization,
const NetAddr& aSelfAddr, const NetAddr& aPeerAddr,
const uint32_t& aCacheKey, const nsCString& altDataType,
const int64_t& altDataLen, const bool& deliveringAltData,
already_AddRefed<nsIInputStream> originalCacheInputStream,
already_AddRefed<nsIInputStream> altDataInputStream,
const bool& aApplyConversion, const bool& aIsResolvedByTRR,
const ResourceTimingStruct& aTiming)
StartRequestEvent(
HttpChannelChild* aChild, const nsresult& aChannelStatus,
const nsHttpResponseHead& aResponseHead, const bool& aUseResponseHead,
const nsHttpHeaderArray& aRequestHeaders,
const ParentLoadInfoForwarderArgs& loadInfoForwarder,
const bool& aIsFromCache, const bool& aIsRacing,
const bool& aCacheEntryAvailable, const uint64_t& aCacheEntryId,
const int32_t& aCacheFetchCount, const uint32_t& aCacheExpirationTime,
const nsCString& aCachedCharset,
const nsCString& aSecurityInfoSerialization, const NetAddr& aSelfAddr,
const NetAddr& aPeerAddr, const uint32_t& aCacheKey,
const nsCString& altDataType, const int64_t& altDataLen,
const bool& deliveringAltData, const bool& aApplyConversion,
const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming)
: NeckoTargetChannelEvent<HttpChannelChild>(aChild),
mChannelStatus(aChannelStatus),
mResponseHead(aResponseHead),
@ -434,8 +429,6 @@ class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
mAltDataType(altDataType),
mAltDataLen(altDataLen),
mDeliveringAltData(deliveringAltData),
mOriginalCacheInputStream(originalCacheInputStream),
mAltDataInputStream(altDataInputStream),
mLoadInfoForwarder(loadInfoForwarder),
mIsResolvedByTRR(aIsResolvedByTRR),
mTiming(aTiming) {}
@ -447,9 +440,8 @@ class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
mLoadInfoForwarder, mIsFromCache, mIsRacing, mCacheEntryAvailable,
mCacheEntryId, mCacheFetchCount, mCacheExpirationTime, mCachedCharset,
mSecurityInfoSerialization, mSelfAddr, mPeerAddr, mCacheKey,
mAltDataType, mAltDataLen, mDeliveringAltData,
mOriginalCacheInputStream.forget(), mAltDataInputStream.forget(),
mApplyConversion, mIsResolvedByTRR, mTiming);
mAltDataType, mAltDataLen, mDeliveringAltData, mApplyConversion,
mIsResolvedByTRR, mTiming);
}
private:
@ -472,8 +464,6 @@ class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild> {
nsCString mAltDataType;
int64_t mAltDataLen;
bool mDeliveringAltData;
nsCOMPtr<nsIInputStream> mOriginalCacheInputStream;
nsCOMPtr<nsIInputStream> mAltDataInputStream;
ParentLoadInfoForwarderArgs mLoadInfoForwarder;
bool mIsResolvedByTRR;
ResourceTimingStruct mTiming;
@ -490,9 +480,7 @@ mozilla::ipc::IPCResult HttpChannelChild::RecvOnStartRequest(
const NetAddr& selfAddr, const NetAddr& peerAddr,
const int16_t& redirectCount, const uint32_t& cacheKey,
const nsCString& altDataType, const int64_t& altDataLen,
const bool& deliveringAltData,
const Maybe<IPCStream>& aOriginalCacheInputStream,
const Maybe<IPCStream>& aAltDataInputStream, const bool& aApplyConversion,
const bool& deliveringAltData, const bool& aApplyConversion,
const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming) {
AUTO_PROFILER_LABEL("HttpChannelChild::RecvOnStartRequest", NETWORK);
LOG(("HttpChannelChild::RecvOnStartRequest [this=%p]\n", this));
@ -507,19 +495,12 @@ mozilla::ipc::IPCResult HttpChannelChild::RecvOnStartRequest(
mRedirectCount = redirectCount;
nsCOMPtr<nsIInputStream> originalCacheInputStream =
DeserializeIPCStream(aOriginalCacheInputStream);
nsCOMPtr<nsIInputStream> altDataInputStream =
DeserializeIPCStream(aAltDataInputStream);
mEventQ->RunOrEnqueue(new StartRequestEvent(
this, channelStatus, responseHead, useResponseHead, requestHeaders,
loadInfoForwarder, isFromCache, isRacing, cacheEntryAvailable,
cacheEntryId, cacheFetchCount, cacheExpirationTime, cachedCharset,
securityInfoSerialization, selfAddr, peerAddr, cacheKey, altDataType,
altDataLen, deliveringAltData, originalCacheInputStream.forget(),
altDataInputStream.forget(), aApplyConversion, aIsResolvedByTRR,
altDataLen, deliveringAltData, aApplyConversion, aIsResolvedByTRR,
aTiming));
{
@ -553,11 +534,8 @@ void HttpChannelChild::OnStartRequest(
const nsCString& cachedCharset, const nsCString& securityInfoSerialization,
const NetAddr& selfAddr, const NetAddr& peerAddr, const uint32_t& cacheKey,
const nsCString& altDataType, const int64_t& altDataLen,
const bool& deliveringAltData,
already_AddRefed<nsIInputStream> originalCacheInputStream,
already_AddRefed<nsIInputStream> altDataInputStream,
const bool& aApplyConversion, const bool& aIsResolvedByTRR,
const ResourceTimingStruct& aTiming) {
const bool& deliveringAltData, const bool& aApplyConversion,
const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming) {
LOG(("HttpChannelChild::OnStartRequest [this=%p]\n", this));
// mFlushedForDiversion and mDivertingToParent should NEVER be set at this
@ -569,9 +547,6 @@ void HttpChannelChild::OnStartRequest(
!mDivertingToParent,
"mDivertingToParent should be unset before OnStartRequest!");
mOriginalCacheInputStream = originalCacheInputStream;
mAltDataInputStream = altDataInputStream;
// If this channel was aborted by ActorDestroy, then there may be other
// OnStartRequest/OnStopRequest/OnDataAvailable IPC messages that need to
// be handled. In that case we just ignore them to avoid calling the listener
@ -3261,29 +3236,62 @@ HttpChannelChild::OpenAlternativeOutputStream(const nsACString& aType,
}
NS_IMETHODIMP
HttpChannelChild::GetOriginalInputStream(nsIInputStream** aInputStream) {
NS_ENSURE_ARG_POINTER(aInputStream);
HttpChannelChild::GetOriginalInputStream(nsIInputStreamReceiver* aReceiver) {
if (aReceiver == nullptr) {
return NS_ERROR_INVALID_ARG;
}
if (!mIPCOpen) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIInputStream> is = mOriginalCacheInputStream;
is.forget(aInputStream);
mOriginalInputStreamReceiver = aReceiver;
Unused << SendOpenOriginalCacheInputStream();
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetAlternativeDataInputStream(nsIInputStream** aInputStream) {
NS_ENSURE_ARG_POINTER(aInputStream);
HttpChannelChild::GetAltDataInputStream(const nsACString& aType,
nsIInputStreamReceiver* aReceiver) {
if (aReceiver == nullptr) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIInputStream> is = mAltDataInputStream;
is.forget(aInputStream);
if (!mIPCOpen) {
return NS_ERROR_NOT_AVAILABLE;
}
mAltDataInputStreamReceiver = aReceiver;
Unused << SendOpenAltDataCacheInputStream(nsCString(aType));
return NS_OK;
}
mozilla::ipc::IPCResult HttpChannelChild::RecvOriginalCacheInputStreamAvailable(
const Maybe<IPCStream>& aStream) {
nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(aStream);
nsCOMPtr<nsIInputStreamReceiver> receiver;
receiver.swap(mOriginalInputStreamReceiver);
if (receiver) {
receiver->OnInputStreamReady(stream);
}
return IPC_OK();
}
mozilla::ipc::IPCResult HttpChannelChild::RecvAltDataCacheInputStreamAvailable(
const Maybe<IPCStream>& aStream) {
nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(aStream);
nsCOMPtr<nsIInputStreamReceiver> receiver;
receiver.swap(mAltDataInputStreamReceiver);
if (receiver) {
receiver->OnInputStreamReady(stream);
}
return IPC_OK();
}
//-----------------------------------------------------------------------------
// HttpChannelChild::nsIResumableChannel
//-----------------------------------------------------------------------------

View File

@ -146,9 +146,7 @@ class HttpChannelChild final : public PHttpChannelChild,
const NetAddr& peerAddr, const int16_t& redirectCount,
const uint32_t& cacheKey, const nsCString& altDataType,
const int64_t& altDataLen, const bool& deliveringAltData,
const Maybe<IPCStream>& originalCacheInputStream,
const Maybe<IPCStream>& altDataInputStream, const bool& aApplyConversion,
const bool& aIsResolvedByTRR,
const bool& aApplyConversion, const bool& aIsResolvedByTRR,
const ResourceTimingStruct& aTiming) override;
mozilla::ipc::IPCResult RecvFailedAsyncOpen(const nsresult& status) override;
mozilla::ipc::IPCResult RecvRedirect1Begin(
@ -179,6 +177,12 @@ class HttpChannelChild final : public PHttpChannelChild,
mozilla::ipc::IPCResult RecvCancelRedirected() override;
mozilla::ipc::IPCResult RecvOriginalCacheInputStreamAvailable(
const Maybe<IPCStream>& aStream) override;
mozilla::ipc::IPCResult RecvAltDataCacheInputStreamAvailable(
const Maybe<IPCStream>& aStream) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual void DoNotifyListenerCleanup() override;
@ -346,8 +350,8 @@ class HttpChannelChild final : public PHttpChannelChild,
nsCOMPtr<nsICacheInfoChannel> mSynthesizedCacheInfo;
RefPtr<ChannelEventQueue> mEventQ;
nsCOMPtr<nsIInputStream> mOriginalCacheInputStream;
nsCOMPtr<nsIInputStream> mAltDataInputStream;
nsCOMPtr<nsIInputStreamReceiver> mOriginalInputStreamReceiver;
nsCOMPtr<nsIInputStreamReceiver> mAltDataInputStreamReceiver;
// Used to ensure atomicity of mBgChild and mBgInitFailCallback
Mutex mBgChildMutex;
@ -474,11 +478,8 @@ class HttpChannelChild final : public PHttpChannelChild,
const nsCString& securityInfoSerialization, const NetAddr& selfAddr,
const NetAddr& peerAddr, const uint32_t& cacheKey,
const nsCString& altDataType, const int64_t& altDataLen,
const bool& deliveringAltData,
already_AddRefed<nsIInputStream> originalCacheInputStream,
already_AddRefed<nsIInputStream> altDataInputStream,
const bool& aApplyConversion, const bool& aIsResolvedByTRR,
const ResourceTimingStruct& aTiming);
const bool& deliveringAltData, const bool& aApplyConversion,
const bool& aIsResolvedByTRR, const ResourceTimingStruct& aTiming);
void MaybeDivertOnData(const nsCString& data, const uint64_t& offset,
const uint32_t& count);
void OnTransportAndData(const nsresult& channelStatus, const nsresult& status,

View File

@ -1467,33 +1467,6 @@ HttpChannelParent::OnStartRequest(nsIRequest* aRequest) {
bool isResolvedByTRR = false;
chan->GetIsResolvedByTRR(&isResolvedByTRR);
AutoIPCStream originalCacheInputStream(true /* delay start */);
AutoIPCStream altDataInputStream(true /* delay start */);
if (mCacheEntry) {
PContentParent* pcp = Manager()->Manager();
{
nsCOMPtr<nsIInputStream> inputStream;
nsresult rv =
mCacheEntry->OpenInputStream(0, getter_AddRefs(inputStream));
if (NS_SUCCEEDED(rv)) {
Unused << originalCacheInputStream.Serialize(
inputStream, static_cast<ContentParent*>(pcp));
}
}
if (!altDataType.IsEmpty()) {
nsCOMPtr<nsIInputStream> inputStream;
nsresult rv = mCacheEntry->OpenAlternativeInputStream(
altDataType, getter_AddRefs(inputStream));
if (NS_SUCCEEDED(rv)) {
Unused << altDataInputStream.Serialize(
inputStream, static_cast<ContentParent*>(pcp));
}
}
}
rv = NS_OK;
if (mIPCClosed ||
!SendOnStartRequest(
@ -1503,9 +1476,7 @@ HttpChannelParent::OnStartRequest(nsIRequest* aRequest) {
mCacheEntry ? true : false, cacheEntryId, fetchCount, expirationTime,
cachedCharset, secInfoSerialization, chan->GetSelfAddr(),
chan->GetPeerAddr(), redirectCount, cacheKey, altDataType, altDataLen,
deliveringAltData, originalCacheInputStream.TakeOptionalValue(),
altDataInputStream.TakeOptionalValue(), applyConversion,
isResolvedByTRR, timing)) {
deliveringAltData, applyConversion, isResolvedByTRR, timing)) {
rv = NS_ERROR_UNEXPECTED;
}
requestHead->Exit();
@ -1721,6 +1692,48 @@ mozilla::ipc::IPCResult HttpChannelParent::RecvBytesRead(
return IPC_OK();
}
mozilla::ipc::IPCResult HttpChannelParent::RecvOpenOriginalCacheInputStream() {
if (mIPCClosed) {
return IPC_OK();
}
AutoIPCStream autoStream;
if (mCacheEntry) {
nsCOMPtr<nsIInputStream> inputStream;
nsresult rv = mCacheEntry->OpenInputStream(0, getter_AddRefs(inputStream));
if (NS_SUCCEEDED(rv)) {
PContentParent* pcp = Manager()->Manager();
Unused << autoStream.Serialize(inputStream,
static_cast<ContentParent*>(pcp));
}
}
Unused << SendOriginalCacheInputStreamAvailable(
autoStream.TakeOptionalValue());
return IPC_OK();
}
mozilla::ipc::IPCResult HttpChannelParent::RecvOpenAltDataCacheInputStream(
const nsCString& aType) {
if (mIPCClosed) {
return IPC_OK();
}
AutoIPCStream autoStream;
if (mCacheEntry) {
nsCOMPtr<nsIInputStream> inputStream;
nsresult rv = mCacheEntry->OpenAlternativeInputStream(
aType, getter_AddRefs(inputStream));
if (NS_SUCCEEDED(rv)) {
PContentParent* pcp = Manager()->Manager();
Unused << autoStream.Serialize(inputStream,
static_cast<ContentParent*>(pcp));
}
}
Unused << SendAltDataCacheInputStreamAvailable(
autoStream.TakeOptionalValue());
return IPC_OK();
}
//-----------------------------------------------------------------------------
// HttpChannelParent::nsIProgressEventSink
//-----------------------------------------------------------------------------

View File

@ -205,6 +205,9 @@ class HttpChannelParent final : public nsIInterfaceRequestor,
const URIParams& uri,
const mozilla::ipc::PrincipalInfo& requestingPrincipal) override;
virtual mozilla::ipc::IPCResult RecvBytesRead(const int32_t& aCount) override;
virtual mozilla::ipc::IPCResult RecvOpenOriginalCacheInputStream() override;
virtual mozilla::ipc::IPCResult RecvOpenAltDataCacheInputStream(
const nsCString& aType) override;
virtual void ActorDestroy(ActorDestroyReason why) override;
// Supporting function for ADivertableParentChannel.

View File

@ -1284,18 +1284,19 @@ InterceptedHttpChannel::OpenAlternativeOutputStream(
}
NS_IMETHODIMP
InterceptedHttpChannel::GetOriginalInputStream(nsIInputStream** aStream) {
InterceptedHttpChannel::GetOriginalInputStream(
nsIInputStreamReceiver* aReceiver) {
if (mSynthesizedCacheInfo) {
return mSynthesizedCacheInfo->GetOriginalInputStream(aStream);
return mSynthesizedCacheInfo->GetOriginalInputStream(aReceiver);
}
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
InterceptedHttpChannel::GetAlternativeDataInputStream(
nsIInputStream** aInputStream) {
InterceptedHttpChannel::GetAltDataInputStream(
const nsACString& aType, nsIInputStreamReceiver* aReceiver) {
if (mSynthesizedCacheInfo) {
return mSynthesizedCacheInfo->GetAlternativeDataInputStream(aInputStream);
return mSynthesizedCacheInfo->GetAltDataInputStream(aType, aReceiver);
}
return NS_ERROR_NOT_AVAILABLE;
}

View File

@ -94,6 +94,12 @@ parent:
// sure not to send any more messages after that.
async DeletingChannel();
// Called to get the input stream when altData was delivered.
async OpenOriginalCacheInputStream();
// Called to get the input stream when altData is available.
async OpenAltDataCacheInputStream(nsCString aType);
// Tell the parent the amount bytes read by child for the e10s back pressure
// flow control
async BytesRead(int32_t count);
@ -121,8 +127,6 @@ child:
nsCString altDataType,
int64_t altDataLength,
bool deliveringAltData,
IPCStream? originalCacheInputStream,
IPCStream? altDataInputStream,
bool applyConversion,
bool isResolvedByTRR,
ResourceTimingStruct timing);
@ -181,6 +185,10 @@ child:
// See ADivertableParentChannel::CancelDiversion
async CancelDiversion();
async OriginalCacheInputStreamAvailable(IPCStream? stream);
async AltDataCacheInputStreamAvailable(IPCStream? stream);
both:
// After receiving this message, the parent also calls
// SendFinishInterceptedRedirect, and makes sure not to send any more messages

View File

@ -8613,39 +8613,38 @@ nsHttpChannel::OpenAlternativeOutputStream(const nsACString& type,
}
NS_IMETHODIMP
nsHttpChannel::GetOriginalInputStream(nsIInputStream** aInputStream) {
NS_ENSURE_ARG_POINTER(aInputStream);
*aInputStream = nullptr;
nsHttpChannel::GetOriginalInputStream(nsIInputStreamReceiver* aReceiver) {
if (aReceiver == nullptr) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIInputStream> inputStream;
nsCOMPtr<nsICacheEntry> cacheEntry =
mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
if (cacheEntry) {
nsresult rv = cacheEntry->OpenInputStream(0, aInputStream);
NS_ENSURE_SUCCESS(rv, rv);
cacheEntry->OpenInputStream(0, getter_AddRefs(inputStream));
}
aReceiver->OnInputStreamReady(inputStream);
return NS_OK;
}
NS_IMETHODIMP
nsHttpChannel::GetAlternativeDataInputStream(nsIInputStream** aInputStream) {
NS_ENSURE_ARG_POINTER(aInputStream);
*aInputStream = nullptr;
if (!mAfterOnStartRequestBegun) {
return NS_ERROR_NOT_AVAILABLE;
nsHttpChannel::GetAltDataInputStream(const nsACString& aType,
nsIInputStreamReceiver* aReceiver) {
if (aReceiver == nullptr) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIInputStream> inputStream;
nsCOMPtr<nsICacheEntry> cacheEntry =
mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
if (!mAvailableCachedAltDataType.IsEmpty() && cacheEntry) {
if (cacheEntry) {
nsresult rv = cacheEntry->OpenAlternativeInputStream(
mAvailableCachedAltDataType, aInputStream);
aType, getter_AddRefs(inputStream));
NS_ENSURE_SUCCESS(rv, rv);
}
aReceiver->OnInputStreamReady(inputStream);
return NS_OK;
}

View File

@ -150,7 +150,11 @@ function readAltContent(request, buffer)
Assert.equal(buffer, altContent);
check_has_alt_data_in_index(true);
executeSoon(() => readOriginalInputStream(cc.originalInputStream));
cc.getOriginalInputStream({
onInputStreamReady: function(aInputStream) {
executeSoon(() => readOriginalInputStream(aInputStream));
}
});
}
function readOriginalInputStream(aInputStream)

View File

@ -144,6 +144,10 @@ var originalListener = {
function testAltDataStream(cc)
{
Assert.ok(!!cc.alternativeDataInputStream);
httpServer.stop(do_test_finished);
cc.getAltDataInputStream(altContentType, {
onInputStreamReady: function(aInputStream) {
Assert.ok(!!aInputStream);
httpServer.stop(do_test_finished);
}
});
}

View File

@ -9,6 +9,12 @@ var cacheFlushObserver = { observe: function() {
// We get this from the child a bit later
var URL = null;
// needs to be rooted
var cacheFlushObserver2 = { observe: function() {
cacheFlushObserver2 = null;
openAltChannel();
}};
function run_test() {
do_get_profile();
do_await_remote_message('flush').then(() => {
@ -44,7 +50,31 @@ function readTextData(request, buffer)
// Now let's generate some alt-data in the parent, and make sure we can get it
var altContent = "altContentParentGenerated";
executeSoon(() => {
Assert.throws(() => cc.openAlternativeOutputStream("text/parent-binary", altContent.length), /NS_ERROR_NOT_AVAILABLE/);
do_send_remote_message('finish');
var os = cc.openAlternativeOutputStream("text/parent-binary", altContent.length);
os.write(altContent, altContent.length);
os.close();
executeSoon(() => {
Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver2);
});
});
}
function openAltChannel() {
var chan = make_channel(URL);
var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
cc.preferAlternativeDataType("text/parent-binary", "", true);
chan.asyncOpen(new ChannelListener(readAltData, null));
}
function readAltData(request, buffer)
{
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
// This was generated in the parent, so it's OK to get it.
Assert.equal(buffer, "altContentParentGenerated");
Assert.equal(cc.alternativeDataType, "text/parent-binary");
// FINISH
do_send_remote_message('finish');
}