This commit is contained in:
Ryan VanderMeulen 2013-09-26 21:32:43 -04:00
Родитель f2641c9a83 de2f4e649f
Коммит 4ee712cb39
27 изменённых файлов: 825 добавлений и 556 удалений

Просмотреть файл

@ -0,0 +1,25 @@
{
"config_version": 2,
"tooltool_manifest": "releng-emulator-ics.tt",
"mock_target": "mozilla-centos6-x86_64",
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "glibc-devel.i686", "libstdc++.i686", "zlib-devel.i686", "ncurses-devel.i686", "libX11-devel.i686", "mesa-libGL-devel.i686", "mesa-libGL-devel", "libX11-devel", "git"],
"mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
"build_targets": ["droid", "package-emulator", "package-tests"],
"upload_files": [
"{workdir}/out/target/product/generic/*.tar.bz2",
"{workdir}/out/target/product/generic/tests/*.zip",
"{workdir}/out/emulator.tar.gz",
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{workdir}/sources.xml"
],
"upload_platform": "emulator-ics",
"gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
"gaia": {
"l10n": {
"vcs": "hgtool",
"root": "http://hg.mozilla.org/gaia-l10n"
}
},
"b2g_manifest": "emulator.xml",
"b2g_manifest_branch": "master"
}

Просмотреть файл

@ -0,0 +1,2 @@
[
]

Просмотреть файл

@ -1,4 +1,4 @@
{
"revision": "43bc58df001f2b870fd2d1eb80723cfdccdc7b67",
"revision": "c9f88878f616a439db6c6be66378af79249f7528",
"repo_path": "/integration/gaia-central"
}

Просмотреть файл

@ -30,99 +30,293 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(MediaRecorder, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(MediaRecorder, nsDOMEventTargetHelper)
// This task is used for triggering the creating blob object and it runs at main thread.
class MediaRecorder::PushBlobTask : public nsRunnable
/**
* Session is an object to represent a single recording event.
* In original design, all recording context is stored in MediaRecorder, which causes
* a problem if someone calls MediaRecoder::Stop and MedaiRecorder::Start quickly.
* To prevent blocking main thread, media encoding is executed in a second thread,
* named as Read Thread. For the same reason, we do not wait Read Thread shutdown in
* MediaRecorder::Stop. If someone call MediaRecoder::Start before Read Thread shutdown,
* the same recording context in MediaRecoder might be access by two Reading Threads,
* which cause a problem.
* In the new design, we put recording context into Session object, including Read
* Thread. Each Session has its own recording context and Read Thread, problem is been
* resolved.
*
* Life cycle of a Session object.
* 1) Initialization Stage (in main thread)
* Setup media streams in MSG, and bind MediaEncoder with Source Stream.
* Resource allocation, such as encoded data cache buffer and MediaEncoder.
* Create read thread.
* Automatically switch to Extract stage in the end of this stage.
* 2) Extract Stage (in Read Thread)
* Pull encoded A/V frames from MediaEncoder, dispatch to OnDataAvailable handler.
* Unless a client calls Session::Stop, Session object keeps stay in this stage.
* 3) Destroy Stage (in main thread)
* Switch from Extract stage to Destroy stage by calling Session::Stop.
* Release session resource and remove associated streams from MSG.
*
* Lifetime of a Session object.
* 1) MediaRecorder creates a Session in MediaRecorder::Start function.
* 2) A Session is destroyed in DestroyRunnable after MediaRecorder::Stop being called
* _and_ all encoded media data been passed to OnDataAvailable handler.
*/
class MediaRecorder::Session
{
public:
PushBlobTask(MediaRecorder* recorder)
: mRecorder(recorder) {}
NS_IMETHODIMP Run()
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = mRecorder->CreateAndDispatchBlobEvent();
if (NS_FAILED(rv)) {
mRecorder->NotifyError(rv);
}
return NS_OK;
}
MediaRecorder* mRecorder;
};
// This task is for firing the error message from encoder and it runs in main thread
class MediaRecorder::PushErrorMessageTask : public nsRunnable
{
public:
PushErrorMessageTask(MediaRecorder* recorder, nsresult aError)
: mRecorder(recorder),
mError(aError) { }
NS_IMETHODIMP Run()
{
MOZ_ASSERT(NS_IsMainThread());
mRecorder->NotifyError(mError);
return NS_OK;
}
private:
MediaRecorder* mRecorder;
nsresult mError;
};
// This class is used for avoiding abort by directly use the NS_NewRunnableMethod and invoke ExtractEncodedData function
// The abort is checking if the destructor runs at main thread during the cycle-collect step in nsDOMEventTargetHelper
class MediaRecorder::ExtractEncodedDataTask : public nsRunnable
{
public:
ExtractEncodedDataTask(MediaRecorder* aRecorder, MediaEncoder* aEncoder)
: mRecorder(aRecorder),
mEncoder(aEncoder) {}
class ReleaseEncoderThreadTask : public nsRunnable
// Main thread task.
// Create a blob event and send back to client.
class PushBlobRunnable : public nsRunnable
{
public:
ReleaseEncoderThreadTask(already_AddRefed<MediaRecorder> recorder)
: mRecorder(recorder) {}
PushBlobRunnable(Session* aSession)
: mSession(aSession)
{ }
NS_IMETHODIMP Run()
{
MOZ_ASSERT(NS_IsMainThread());
mRecorder->mReadThread->Shutdown();
mRecorder->mReadThread = nullptr;
// Setting mState to Inactive here is for the case where SourceStream
// ends itself, thus the recorder should stop itself too.
mRecorder->mState = RecordingState::Inactive;
mRecorder->DispatchSimpleEvent(NS_LITERAL_STRING("stop"));
MediaRecorder *recorder = mSession->mRecorder;
nsresult rv = recorder->CreateAndDispatchBlobEvent(mSession);
if (NS_FAILED(rv)) {
recorder->NotifyError(rv);
}
return NS_OK;
}
private:
nsRefPtr<MediaRecorder> mRecorder;
Session *mSession;
};
NS_IMETHODIMP Run()
// Record thread task.
// Fetch encoded Audio/Video data from MediaEncoder.
class ExtractRunnable : public nsRunnable
{
MOZ_ASSERT(!NS_IsMainThread());
mRecorder->ExtractEncodedData();
NS_DispatchToMainThread(new ReleaseEncoderThreadTask(mRecorder.forget()));
return NS_OK;
public:
ExtractRunnable(Session *aSession)
: mSession(aSession) {}
NS_IMETHODIMP Run()
{
MOZ_ASSERT(NS_GetCurrentThread() == mSession->mReadThread);
mSession->Extract();
return NS_OK;
}
private:
Session *mSession;
};
// Main thread task.
// To delete RecordingSession object.
class DestroyRunnable : public nsRunnable
{
public:
DestroyRunnable(Session *aSession)
: mSession(aSession) {}
NS_IMETHODIMP Run()
{
MOZ_ASSERT(NS_IsMainThread() && mSession.get());
MediaRecorder *recorder = mSession->mRecorder;
// If MediaRecoder is not in Inactive mode, call MediaRecoder::Stop
// and dispatch DestroyRunnable again.
if (recorder->mState != RecordingState::Inactive) {
ErrorResult result;
recorder->Stop(result);
NS_DispatchToMainThread(new DestroyRunnable(mSession.forget()));
return NS_OK;
}
// Dispatch stop event and clear MIME type.
recorder->DispatchSimpleEvent(NS_LITERAL_STRING("stop"));
recorder->SetMimeType(NS_LITERAL_STRING(""));
// Delete session object.
mSession = nullptr;
return NS_OK;
}
private:
nsAutoPtr<Session> mSession;
};
friend class PushBlobRunnable;
friend class ExtractRunnable;
friend class DestroyRunnable;
public:
Session(MediaRecorder* aRecorder, int32_t aTimeSlice)
: mRecorder(aRecorder),
mTimeSlice(aTimeSlice)
{
MOZ_ASSERT(NS_IsMainThread());
mEncodedBufferCache = new EncodedBufferCache(MAX_ALLOW_MEMORY_BUFFER);
}
// Only DestroyRunnable is allowed to delete Session object.
~Session()
{
MOZ_ASSERT(NS_IsMainThread());
if (mInputPort.get()) {
mInputPort->Destroy();
}
if (mTrackUnionStream.get()) {
mTrackUnionStream->Destroy();
}
}
void Start()
{
MOZ_ASSERT(NS_IsMainThread());
SetupStreams();
// Create a thread to read encode media data from MediaEncoder.
if (!mReadThread) {
nsresult rv = NS_NewNamedThread("Media Encoder", getter_AddRefs(mReadThread));
if (NS_FAILED(rv)) {
mRecorder->NotifyError(rv);
return;
}
}
mReadThread->Dispatch(new ExtractRunnable(this), NS_DISPATCH_NORMAL);
}
void Stop()
{
MOZ_ASSERT(NS_IsMainThread());
// Shutdown mEncoder to stop Session::Extract
if (mInputPort.get())
{
mInputPort->Destroy();
mInputPort = nullptr;
}
if (mTrackUnionStream.get())
{
mTrackUnionStream->Destroy();
mTrackUnionStream = nullptr;
}
}
void Pause()
{
MOZ_ASSERT(NS_IsMainThread() && mTrackUnionStream);
mTrackUnionStream->ChangeExplicitBlockerCount(-1);
}
void Resume()
{
MOZ_ASSERT(NS_IsMainThread() && mTrackUnionStream);
mTrackUnionStream->ChangeExplicitBlockerCount(1);
}
already_AddRefed<nsIDOMBlob> GetEncodedData()
{
nsString mimeType;
mRecorder->GetMimeType(mimeType);
return mEncodedBufferCache->ExtractBlob(mimeType);
}
private:
// Pull encoded meida data from MediaEncoder and put into EncodedBufferCache.
// Destroy this session object in the end of this function.
void Extract()
{
MOZ_ASSERT(NS_GetCurrentThread() == mReadThread);
TimeStamp lastBlobTimeStamp = TimeStamp::Now();
// Whether push encoded data back to onDataAvailable automatically.
const bool pushBlob = (mTimeSlice > 0) ? true : false;
do {
// Pull encoded media data from MediaEncoder
nsTArray<nsTArray<uint8_t> > encodedBuf;
nsString mimeType;
mEncoder->GetEncodedData(&encodedBuf, mimeType);
mRecorder->SetMimeType(mimeType);
// Append pulled data into cache buffer.
for (uint32_t i = 0; i < encodedBuf.Length(); i++) {
mEncodedBufferCache->AppendBuffer(encodedBuf[i]);
}
if (pushBlob) {
if ((TimeStamp::Now() - lastBlobTimeStamp).ToMilliseconds() > mTimeSlice) {
NS_DispatchToMainThread(new PushBlobRunnable(this));
lastBlobTimeStamp = TimeStamp::Now();
}
}
} while (!mEncoder->IsShutdown());
// Flush out remainding encoded data.
NS_DispatchToMainThread(new PushBlobRunnable(this));
// Destroy this session object in main thread.
NS_DispatchToMainThread(new DestroyRunnable(this));
}
// Bind media source with MediaEncoder to receive raw media data.
void SetupStreams()
{
MOZ_ASSERT(NS_IsMainThread());
MediaStreamGraph* gm = mRecorder->mStream->GetStream()->Graph();
mTrackUnionStream = gm->CreateTrackUnionStream(nullptr);
MOZ_ASSERT(mTrackUnionStream, "CreateTrackUnionStream failed");
mTrackUnionStream->SetAutofinish(true);
mInputPort = mTrackUnionStream->AllocateInputPort(mRecorder->mStream->GetStream(), MediaInputPort::FLAG_BLOCK_OUTPUT);
// Allocate encoder and bind with union stream.
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""));
MOZ_ASSERT(mEncoder, "CreateEncoder failed");
if (mEncoder) {
mTrackUnionStream->AddListener(mEncoder);
}
}
private:
// Hold a reference to MediaRecoder to make sure MediaRecoder be
// destroyed after all session object dead.
nsRefPtr<MediaRecorder> mRecorder;
nsRefPtr<MediaEncoder> mEncoder;
// Pause/ Resume controller.
nsRefPtr<ProcessedMediaStream> mTrackUnionStream;
nsRefPtr<MediaInputPort> mInputPort;
// Runnable thread for read data from MediaEncode.
nsCOMPtr<nsIThread> mReadThread;
// MediaEncoder pipeline.
nsRefPtr<MediaEncoder> mEncoder;
// A buffer to cache encoded meda data.
nsAutoPtr<EncodedBufferCache> mEncodedBufferCache;
// The interval of passing encoded data from EncodedBufferCache to onDataAvailable
// handler. "mTimeSlice < 0" means Session object does not push encoded data to
// onDataAvailable, instead, it passive wait the client side pull encoded data
// by calling requestData API.
const int32_t mTimeSlice;
};
MediaRecorder::~MediaRecorder()
{
if (mStreamPort) {
mStreamPort->Destroy();
}
if (mTrackUnionStream) {
mTrackUnionStream->Destroy();
}
MOZ_ASSERT(mSession == nullptr);
}
void
@ -134,31 +328,26 @@ MediaRecorder::Init(nsPIDOMWindow* aOwnerWindow)
}
MediaRecorder::MediaRecorder(DOMMediaStream& aStream)
: mTimeSlice(0),
mState(RecordingState::Inactive)
: mState(RecordingState::Inactive),
mSession(nullptr),
mMutex("Session.Data.Mutex")
{
mStream = &aStream;
SetIsDOMBinding();
}
void
MediaRecorder::ExtractEncodedData()
MediaRecorder::SetMimeType(const nsString &aMimeType)
{
TimeStamp lastBlobTimeStamp = TimeStamp::Now();
do {
nsTArray<nsTArray<uint8_t> > outputBufs;
mEncoder->GetEncodedData(&outputBufs, mMimeType);
for (uint32_t i = 0; i < outputBufs.Length(); i++) {
mEncodedBufferCache->AppendBuffer(outputBufs[i]);
}
MutexAutoLock lock(mMutex);
mMimeType = aMimeType;
}
if (mTimeSlice > 0 && (TimeStamp::Now() - lastBlobTimeStamp).ToMilliseconds() > mTimeSlice) {
NS_DispatchToMainThread(new PushBlobTask(this));
lastBlobTimeStamp = TimeStamp::Now();
}
} while (!mEncoder->IsShutdown());
NS_DispatchToMainThread(new PushBlobTask(this));
void
MediaRecorder::GetMimeType(nsString &aMimeType)
{
MutexAutoLock lock(mMutex);
aMimeType = mMimeType;
}
void
@ -174,53 +363,25 @@ MediaRecorder::Start(const Optional<int32_t>& aTimeSlice, ErrorResult& aResult)
return;
}
int32_t timeSlice = 0;
if (aTimeSlice.WasPassed()) {
if (aTimeSlice.Value() < 0) {
aResult.Throw(NS_ERROR_INVALID_ARG);
return;
}
mTimeSlice = aTimeSlice.Value();
} else {
mTimeSlice = 0;
}
// Create a TrackUnionStream to support Pause/Resume by using ChangeExplicitBlockerCount
MediaStreamGraph* gm = mStream->GetStream()->Graph();
mTrackUnionStream = gm->CreateTrackUnionStream(nullptr);
MOZ_ASSERT(mTrackUnionStream, "CreateTrackUnionStream failed");
timeSlice = aTimeSlice.Value();
}
if (!CheckPrincipal()) {
aResult.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
if (mEncodedBufferCache == nullptr) {
mEncodedBufferCache = new EncodedBufferCache(MAX_ALLOW_MEMORY_BUFFER);
}
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""));
MOZ_ASSERT(mEncoder, "CreateEncoder failed");
mTrackUnionStream->SetAutofinish(true);
mStreamPort = mTrackUnionStream->AllocateInputPort(mStream->GetStream(), MediaInputPort::FLAG_BLOCK_OUTPUT);
if (mEncoder) {
mTrackUnionStream->AddListener(mEncoder);
} else {
aResult.Throw(NS_ERROR_DOM_ABORT_ERR);
}
if (!mReadThread) {
nsresult rv = NS_NewNamedThread("Media Encoder",
getter_AddRefs(mReadThread));
if (NS_FAILED(rv)) {
aResult.Throw(rv);
return;
}
nsRefPtr<ExtractEncodedDataTask> event = new ExtractEncodedDataTask(this, mEncoder);
mReadThread->Dispatch(event, NS_DISPATCH_NORMAL);
mState = RecordingState::Recording;
}
mState = RecordingState::Recording;
// Start a session
mSession = new Session(this, timeSlice);
mSession->Start();
}
void
@ -230,13 +391,11 @@ MediaRecorder::Stop(ErrorResult& aResult)
aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
mSession->Stop();
mSession = nullptr;
mState = RecordingState::Inactive;
mStreamPort->Destroy();
mStreamPort = nullptr;
mTrackUnionStream->Destroy();
mTrackUnionStream = nullptr;
}
void
@ -246,9 +405,14 @@ MediaRecorder::Pause(ErrorResult& aResult)
aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
mTrackUnionStream->ChangeExplicitBlockerCount(-1);
mState = RecordingState::Paused;
MOZ_ASSERT(mSession != nullptr);
if (mSession) {
mSession->Pause();
mState = RecordingState::Paused;
}
}
void
@ -258,8 +422,12 @@ MediaRecorder::Resume(ErrorResult& aResult)
aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
mTrackUnionStream->ChangeExplicitBlockerCount(1);
mState = RecordingState::Recording;
MOZ_ASSERT(mSession != nullptr);
if (mSession) {
mSession->Resume();
mState = RecordingState::Recording;
}
}
void
@ -269,8 +437,11 @@ MediaRecorder::RequestData(ErrorResult& aResult)
aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
NS_DispatchToMainThread(NS_NewRunnableMethod(this, &MediaRecorder::CreateAndDispatchBlobEvent),
NS_DISPATCH_NORMAL);
NS_DispatchToMainThread(
NS_NewRunnableMethodWithArg<Session *>(this,
&MediaRecorder::CreateAndDispatchBlobEvent, mSession),
NS_DISPATCH_NORMAL);
}
JSObject*
@ -301,7 +472,7 @@ MediaRecorder::Constructor(const GlobalObject& aGlobal,
}
nsresult
MediaRecorder::CreateAndDispatchBlobEvent()
MediaRecorder::CreateAndDispatchBlobEvent(Session *aSession)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
@ -313,7 +484,7 @@ MediaRecorder::CreateAndDispatchBlobEvent()
BlobEventInitInitializer init;
init.mBubbles = false;
init.mCancelable = false;
init.mData = mEncodedBufferCache->ExtractBlob(mMimeType);
init.mData = aSession->GetEncodedData();
nsRefPtr<BlobEvent> event =
BlobEvent::Constructor(this,
NS_LITERAL_STRING("dataavailable"),

Просмотреть файл

@ -36,9 +36,8 @@ namespace dom {
class MediaRecorder : public nsDOMEventTargetHelper
{
class ExtractEncodedDataTask;
class PushBlobTask;
class PushErrorMessageTask;
class Session;
public:
MediaRecorder(DOMMediaStream&);
virtual ~MediaRecorder();
@ -71,7 +70,7 @@ public:
// The current state of the MediaRecorder object.
RecordingState State() const { return mState; }
// Return the current encoding MIME type selected by the MediaEncoder.
void GetMimeType(nsString &aMimeType) { aMimeType = mMimeType; }
void GetMimeType(nsString &aMimeType);
static already_AddRefed<MediaRecorder>
Constructor(const GlobalObject& aGlobal,
@ -83,45 +82,33 @@ public:
IMPL_EVENT_HANDLER(stop)
IMPL_EVENT_HANDLER(warning)
friend class ExtractEncodedData;
protected:
void Init(nsPIDOMWindow* aOwnerWindow);
// Copy encoded data from encoder to EncodedBufferCache. This function runs in the Media Encoder Thread.
void ExtractEncodedData();
MediaRecorder& operator = (const MediaRecorder& x) MOZ_DELETE;
// Create dataavailable event with Blob data and it runs in main thread
nsresult CreateAndDispatchBlobEvent();
nsresult CreateAndDispatchBlobEvent(Session *session);
// Creating a simple event to notify UA simple event.
void DispatchSimpleEvent(const nsAString & aStr);
// Creating a error event with message.
void NotifyError(nsresult aRv);
// Check if the recorder's principal is the subsume of mediaStream
bool CheckPrincipal();
// Set encoded MIME type.
void SetMimeType(const nsString &aMimeType);
MediaRecorder(const MediaRecorder& x) MOZ_DELETE; // prevent bad usage
// Runnable thread for read data from mediaEncoder. It starts at MediaRecorder::Start() and stops at MediaRecorder::Stop().
nsCOMPtr<nsIThread> mReadThread;
// The MediaEncoder object initializes on start() and destroys in ~MediaRecorder.
nsRefPtr<MediaEncoder> mEncoder;
// MediaStream passed from js context
nsRefPtr<DOMMediaStream> mStream;
// This media stream is used for notifying raw data to encoder and can be blocked.
nsRefPtr<ProcessedMediaStream> mTrackUnionStream;
// This is used for destroing the inputport when destroy the mediaRecorder
nsRefPtr<MediaInputPort> mStreamPort;
// This object creates on start() and destroys in ~MediaRecorder.
nsAutoPtr<EncodedBufferCache> mEncodedBufferCache;
// It specifies the container format as well as the audio and video capture formats.
nsString mMimeType;
// The interval of timer passed from Start(). On every mTimeSlice milliseconds, if there are buffers store in the EncodedBufferCache,
// a dataavailable event will be fired.
int32_t mTimeSlice;
// The current state of the MediaRecorder object.
RecordingState mState;
// Current recording session.
Session *mSession;
// Thread safe for mMimeType.
Mutex mMutex;
// It specifies the container format as well as the audio and video capture formats.
nsString mMimeType;
};
}

Просмотреть файл

@ -128,6 +128,7 @@ MOCHITEST_FILES = \
test_mediarecorder_record_no_timeslice.html \
test_mediarecorder_reload_crash.html \
test_mediarecorder_record_immediate_stop.html \
test_mediarecorder_record_session.html \
test_media_selection.html \
test_playback.html \
test_seekLies.html \

Просмотреть файл

@ -0,0 +1,72 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=909670
-->
<head>
<meta charset="utf-8">
<title>Test for Media Recoder recording session</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
var manager = new MediaTestManager;
function startTest(test, token) {
var element = document.createElement('audio');
element.token = token;
manager.started(token);
element.src = test.name;
element.test = test;
element.stream = element.mozCaptureStream();
var mStopCount = 0;
// Start and stop recording session three times continuously.
var mExpectStopCount = 3;
var mediaRecorder = new MediaRecorder(element.stream);
// Stop callback.
// Suppose to receive mExpectStopCount
mediaRecorder.onstop = function stopCallback() {
mStopCount++;
info("MediaRecorder.onstop callback: (" + mStopCount + ")");
if (mExpectStopCount === mStopCount)
{
manager.finished(token);
}
}
// data avaliable.
mediaRecorder.ondataavailable = function(evt) {}
mediaRecorder.onerror = function(err) {
ok(false, 'Unexpected error fired with:' + err);
}
mediaRecorder.onwarning = function() {
ok(false, 'Unexpected warning fired');
}
element.oncanplaythrough = function () {
for (var i = 0; i < mExpectStopCount; i++) {
mediaRecorder.start(1000);
mediaRecorder.stop();
}
}
element.play();
}
manager.runTests(gMediaRecorderTests, startTest);
</script>
</pre>
</body>
</html>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -109,7 +109,7 @@ function newIncomingParcel(fakeParcelSize, response, request, data) {
++writeIndex;
}
function writeUint32(value) {
function writeInt32(value) {
writeUint8(value & 0xff);
writeUint8((value >> 8) & 0xff);
writeUint8((value >> 16) & 0xff);
@ -128,8 +128,8 @@ function newIncomingParcel(fakeParcelSize, response, request, data) {
}
writeParcelSize(fakeParcelSize);
writeUint32(response);
writeUint32(request);
writeInt32(response);
writeInt32(request);
// write parcel data
for (let ii = 0; ii < data.length; ++ii) {

Просмотреть файл

@ -42,10 +42,10 @@ add_test(function test_change_call_barring_password() {
function do_test(facility, pin, newPin) {
buf.sendParcel = function fakeSendParcel () {
// Request Type.
do_check_eq(this.readUint32(), REQUEST_CHANGE_BARRING_PASSWORD);
do_check_eq(this.readInt32(), REQUEST_CHANGE_BARRING_PASSWORD);
// Token : we don't care.
this.readUint32();
this.readInt32();
let parcel = this.readStringList();
do_check_eq(parcel.length, 3);

Просмотреть файл

@ -51,7 +51,7 @@ add_test_incoming_parcel(null,
function test_normal_parcel_handling(worker) {
do_check_throws(function normal_handler() {
// reads exactly the same size, should not throw anything.
worker.Buf.readUint32();
worker.Buf.readInt32();
});
}
);

Просмотреть файл

@ -31,7 +31,7 @@ function newWorkerWithParcel(parcelBuf) {
return buf[index++];
};
worker.Buf.readUint32 = function () {
worker.Buf.readInt32 = function () {
return buf[index++];
};

Просмотреть файл

@ -106,7 +106,7 @@ add_test(function test_queryCallForwardStatus_unconditional() {
});
};
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return worker.Buf.int32Array.pop();
};

Просмотреть файл

@ -30,7 +30,7 @@ add_test(function test_queryCLIP_provisioned() {
let workerHelper = _getWorker();
let worker = workerHelper.worker;
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return worker.Buf.int32Array.pop();
};
@ -58,7 +58,7 @@ add_test(function test_getCLIP_error_generic_failure_invalid_length() {
let workerHelper = _getWorker();
let worker = workerHelper.worker;
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return worker.Buf.int32Array.pop();
};

Просмотреть файл

@ -85,7 +85,7 @@ add_test(function test_getCLIR_n0_m1() {
let workerHelper = _getWorker();
let worker = workerHelper.worker;
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return worker.Buf.int32Array.pop();
};
@ -117,7 +117,7 @@ add_test(function test_getCLIR_error_generic_failure_invalid_length() {
let workerHelper = _getWorker();
let worker = workerHelper.worker;
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return worker.Buf.int32Array.pop();
};

Просмотреть файл

@ -74,7 +74,7 @@ add_test(function test_queryCallWaiting_success_enabled_true() {
let workerHelper = _getWorker();
let worker = workerHelper.worker;
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return worker.Buf.int32Array.pop();
};
@ -104,7 +104,7 @@ add_test(function test_queryCallWaiting_success_enabled_false() {
let workerHelper = _getWorker();
let worker = workerHelper.worker;
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return worker.Buf.int32Array.pop();
};

Просмотреть файл

@ -492,13 +492,13 @@ add_test(function test_icc_get_card_lock_state_fdn() {
buf.sendParcel = function () {
// Request Type.
do_check_eq(this.readUint32(), REQUEST_QUERY_FACILITY_LOCK)
do_check_eq(this.readInt32(), REQUEST_QUERY_FACILITY_LOCK)
// Token : we don't care.
this.readUint32();
this.readInt32();
// String Array Length.
do_check_eq(this.readUint32(), worker.RILQUIRKS_V5_LEGACY ? 3 : 4);
do_check_eq(this.readInt32(), worker.RILQUIRKS_V5_LEGACY ? 3 : 4);
// Facility.
do_check_eq(this.readString(), ICC_CB_FACILITY_FDN);
@ -513,7 +513,7 @@ add_test(function test_icc_get_card_lock_state_fdn() {
if (!worker.RILQUIRKS_V5_LEGACY) {
// AID. Ignore because it's from modem.
this.readUint32();
this.readInt32();
}
run_next_test();
@ -759,7 +759,7 @@ add_test(function test_read_pbr() {
];
// Write data size
buf.writeUint32(pbr_1.length * 2);
buf.writeInt32(pbr_1.length * 2);
// Write pbr
for (let i = 0; i < pbr_1.length; i++) {
@ -820,7 +820,7 @@ add_test(function test_read_email() {
0x6F, 0x6D, 0x02, 0x23];
// Write data size
buf.writeUint32(email_1.length * 2);
buf.writeInt32(email_1.length * 2);
// Write email
for (let i = 0; i < email_1.length; i++) {
@ -888,32 +888,32 @@ add_test(function test_update_email() {
count++;
// Request Type.
do_check_eq(this.readUint32(), REQUEST_SIM_IO);
do_check_eq(this.readInt32(), REQUEST_SIM_IO);
// Token : we don't care
this.readUint32();
this.readInt32();
// command.
do_check_eq(this.readUint32(), ICC_COMMAND_UPDATE_RECORD);
do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
// fileId.
do_check_eq(this.readUint32(), fileId);
do_check_eq(this.readInt32(), fileId);
// pathId.
do_check_eq(this.readString(),
EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
// p1.
do_check_eq(this.readUint32(), recordNumber);
do_check_eq(this.readInt32(), recordNumber);
// p2.
do_check_eq(this.readUint32(), READ_RECORD_ABSOLUTE_MODE);
do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
// p3.
do_check_eq(this.readUint32(), recordSize);
do_check_eq(this.readInt32(), recordSize);
// data.
let strLen = this.readUint32();
let strLen = this.readInt32();
let email;
if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
email = pduHelper.read8BitUnpackedToString(recordSize);
@ -930,7 +930,7 @@ add_test(function test_update_email() {
if (!worker.RILQUIRKS_V5_LEGACY) {
// AID. Ignore because it's from modem.
this.readUint32();
this.readInt32();
}
if (count == NUM_TESTS) {
@ -962,7 +962,7 @@ add_test(function test_read_anr() {
0x54, 0xF6, 0xFF, 0xFF];
// Write data size
buf.writeUint32(anr_1.length * 2);
buf.writeInt32(anr_1.length * 2);
// Write anr
for (let i = 0; i < anr_1.length; i++) {
@ -1029,32 +1029,32 @@ add_test(function test_update_anr() {
count++;
// Request Type.
do_check_eq(this.readUint32(), REQUEST_SIM_IO);
do_check_eq(this.readInt32(), REQUEST_SIM_IO);
// Token : we don't care
this.readUint32();
this.readInt32();
// command.
do_check_eq(this.readUint32(), ICC_COMMAND_UPDATE_RECORD);
do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
// fileId.
do_check_eq(this.readUint32(), fileId);
do_check_eq(this.readInt32(), fileId);
// pathId.
do_check_eq(this.readString(),
EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
// p1.
do_check_eq(this.readUint32(), recordNumber);
do_check_eq(this.readInt32(), recordNumber);
// p2.
do_check_eq(this.readUint32(), READ_RECORD_ABSOLUTE_MODE);
do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
// p3.
do_check_eq(this.readUint32(), recordSize);
do_check_eq(this.readInt32(), recordSize);
// data.
let strLen = this.readUint32();
let strLen = this.readInt32();
// EF_AAS, ignore.
pduHelper.readHexOctet();
do_check_eq(pduHelper.readNumberWithLength(), expectedANR);
@ -1073,7 +1073,7 @@ add_test(function test_update_anr() {
if (!worker.RILQUIRKS_V5_LEGACY) {
// AID. Ignore because it's from modem.
this.readUint32();
this.readInt32();
}
if (count == NUM_TESTS) {
@ -1103,7 +1103,7 @@ add_test(function test_read_iap() {
let iap_1 = [0x01, 0x02];
// Write data size/
buf.writeUint32(iap_1.length * 2);
buf.writeInt32(iap_1.length * 2);
// Write iap.
for (let i = 0; i < iap_1.length; i++) {
@ -1172,32 +1172,32 @@ add_test(function test_update_iap() {
function do_test(expectedIAP) {
buf.sendParcel = function () {
// Request Type.
do_check_eq(this.readUint32(), REQUEST_SIM_IO);
do_check_eq(this.readInt32(), REQUEST_SIM_IO);
// Token : we don't care
this.readUint32();
this.readInt32();
// command.
do_check_eq(this.readUint32(), ICC_COMMAND_UPDATE_RECORD);
do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
// fileId.
do_check_eq(this.readUint32(), fileId);
do_check_eq(this.readInt32(), fileId);
// pathId.
do_check_eq(this.readString(),
EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
// p1.
do_check_eq(this.readUint32(), recordNumber);
do_check_eq(this.readInt32(), recordNumber);
// p2.
do_check_eq(this.readUint32(), READ_RECORD_ABSOLUTE_MODE);
do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
// p3.
do_check_eq(this.readUint32(), recordSize);
do_check_eq(this.readInt32(), recordSize);
// data.
let strLen = this.readUint32();
let strLen = this.readInt32();
for (let i = 0; i < recordSize; i++) {
do_check_eq(expectedIAP[i], pduHelper.readHexOctet());
}
@ -1208,7 +1208,7 @@ add_test(function test_update_iap() {
if (!worker.RILQUIRKS_V5_LEGACY) {
// AID. Ignore because it's from modem.
this.readUint32();
this.readInt32();
}
run_next_test();
@ -1246,28 +1246,28 @@ add_test(function test_update_adn_like() {
buf.sendParcel = function () {
// Request Type.
do_check_eq(this.readUint32(), REQUEST_SIM_IO);
do_check_eq(this.readInt32(), REQUEST_SIM_IO);
// Token : we don't care
this.readUint32();
this.readInt32();
// command.
do_check_eq(this.readUint32(), ICC_COMMAND_UPDATE_RECORD);
do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
// fileId.
do_check_eq(this.readUint32(), fileId);
do_check_eq(this.readInt32(), fileId);
// pathId.
do_check_eq(this.readString(), EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
// p1.
do_check_eq(this.readUint32(), 1);
do_check_eq(this.readInt32(), 1);
// p2.
do_check_eq(this.readUint32(), READ_RECORD_ABSOLUTE_MODE);
do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
// p3.
do_check_eq(this.readUint32(), 0x20);
do_check_eq(this.readInt32(), 0x20);
// data.
let contact = pdu.readAlphaIdDiallingNumber(0x20);
@ -1283,7 +1283,7 @@ add_test(function test_update_adn_like() {
if (!worker.RILQUIRKS_V5_LEGACY) {
// AID. Ignore because it's from modem.
this.readUint32();
this.readInt32();
}
if (fileId == ICC_EF_FDN) {
@ -1313,7 +1313,7 @@ add_test(function test_find_free_record_id() {
function writeRecord (record) {
// Write data size
buf.writeUint32(record.length * 2);
buf.writeInt32(record.length * 2);
for (let i = 0; i < record.length; i++) {
pduHelper.writeHexOctet(record[i]);
@ -1733,10 +1733,10 @@ add_test(function test_set_icc_card_lock_facility_lock() {
function do_test(aLock, aPassword, aEnabled) {
buf.sendParcel = function fakeSendParcel () {
// Request Type.
do_check_eq(this.readUint32(), REQUEST_SET_FACILITY_LOCK);
do_check_eq(this.readInt32(), REQUEST_SET_FACILITY_LOCK);
// Token : we don't care
this.readUint32();
this.readInt32();
let parcel = this.readStringList();
do_check_eq(parcel.length, 5);
@ -1783,14 +1783,14 @@ add_test(function test_unlock_card_lock_corporateLocked() {
function do_test(aLock, aPassword) {
buf.sendParcel = function fakeSendParcel () {
// Request Type.
do_check_eq(this.readUint32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE);
do_check_eq(this.readInt32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE);
// Token : we don't care
this.readUint32();
this.readInt32();
let lockType = GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[aLock];
// Lock Type
do_check_eq(this.readUint32(), lockType);
do_check_eq(this.readInt32(), lockType);
// Pin/Puk.
do_check_eq(this.readString(), aPassword);
@ -1867,7 +1867,7 @@ add_test(function test_reading_ad_and_parsing_mcc_mnc() {
}
// Write data size
buf.writeUint32(ad.length * 2);
buf.writeInt32(ad.length * 2);
// Write data
for (let i = 0; i < ad.length; i++) {

Просмотреть файл

@ -435,7 +435,7 @@ add_test(function test_sendMMI_call_forwarding_interrogation() {
let workerhelper = getWorker();
let worker = workerhelper.worker;
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return worker.Buf.int32Array.pop();
};
@ -477,7 +477,7 @@ add_test(function test_sendMMI_call_forwarding_interrogation_no_rules() {
let workerhelper = getWorker();
let worker = workerhelper.worker;
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return 0;
};
@ -771,7 +771,7 @@ add_test(function test_sendMMI_call_barring_BAIC_interrogation_voice() {
let workerhelper = getWorker();
let worker = workerhelper.worker;
worker.Buf.readUint32List = function fakeReadUint32List() {
worker.Buf.readInt32List = function fakeReadUint32List() {
return [1];
};
@ -954,7 +954,7 @@ add_test(function test_sendMMI_call_waiting_interrogation() {
let workerhelper = getWorker();
let worker = workerhelper.worker;
worker.Buf.readUint32 = function fakeReadUint32() {
worker.Buf.readInt32 = function fakeReadUint32() {
return worker.Buf.int32Array.pop();
};

Просмотреть файл

@ -82,7 +82,7 @@ add_test(function test_read_cdmahome() {
let cdmaHome = [0xc1, 0x34, 0xff, 0xff, 0x00];
// Write data size
buf.writeUint32(cdmaHome.length * 2);
buf.writeInt32(cdmaHome.length * 2);
// Write cdma home file.
for (let i = 0; i < cdmaHome.length; i++) {
@ -128,7 +128,7 @@ add_test(function test_read_cdmaspn() {
function testReadSpn(file, expectedSpn, expectedDisplayCondition) {
io.loadTransparentEF = function fakeLoadTransparentEF(options) {
// Write data size
buf.writeUint32(file.length * 2);
buf.writeInt32(file.length * 2);
// Write file.
for (let i = 0; i < file.length; i++) {

Просмотреть файл

@ -92,16 +92,16 @@ add_test(function test_stk_terminal_response() {
buf.sendParcel = function () {
// Type
do_check_eq(this.readUint32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
do_check_eq(this.readInt32(), REQUEST_STK_SEND_TERMINAL_RESPONSE);
// Token : we don't care
this.readUint32();
this.readInt32();
// Data Size, 44 = 2 * (TLV_COMMAND_DETAILS_SIZE(5) +
// TLV_DEVICE_ID_SIZE(4) +
// TLV_RESULT_SIZE(3) +
// TEXT LENGTH(10))
do_check_eq(this.readUint32(), 44);
do_check_eq(this.readInt32(), 44);
// Command Details, Type-Length-Value
do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
@ -748,16 +748,16 @@ add_test(function test_stk_event_download_location_status() {
buf.sendParcel = function () {
// Type
do_check_eq(this.readUint32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
do_check_eq(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
// Token : we don't care
this.readUint32();
this.readInt32();
// Data Size, 42 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) +
// TLV_EVENT_LIST_SIZE(3) +
// TLV_LOCATION_STATUS_SIZE(3) +
// TLV_LOCATION_INFO_GSM_SIZE(9))
do_check_eq(this.readUint32(), 42);
do_check_eq(this.readInt32(), 42);
// BER tag
do_check_eq(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
@ -830,15 +830,15 @@ add_test(function test_stk_event_download_language_selection() {
buf.sendParcel = function () {
// Type
do_check_eq(this.readUint32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
do_check_eq(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
// Token : we don't care
this.readUint32();
this.readInt32();
// Data Size, 26 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) +
// TLV_EVENT_LIST_SIZE(3) +
// TLV_LANGUAGE(4))
do_check_eq(this.readUint32(), 26);
do_check_eq(this.readInt32(), 26);
// BER tag
do_check_eq(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
@ -888,13 +888,13 @@ add_test(function test_stk_event_download_user_activity() {
buf.sendParcel = function () {
// Type
do_check_eq(this.readUint32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
do_check_eq(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
// Token : we don't care
this.readUint32();
this.readInt32();
// Data Size, 18 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3))
do_check_eq(this.readUint32(), 18);
do_check_eq(this.readInt32(), 18);
// BER tag
do_check_eq(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);
@ -936,13 +936,13 @@ add_test(function test_stk_event_download_idle_screen_available() {
buf.sendParcel = function () {
// Type
do_check_eq(this.readUint32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
do_check_eq(this.readInt32(), REQUEST_STK_SEND_ENVELOPE_COMMAND);
// Token : we don't care
this.readUint32();
this.readInt32();
// Data Size, 18 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) + TLV_EVENT_LIST_SIZE(3))
do_check_eq(this.readUint32(), 18);
do_check_eq(this.readInt32(), 18);
// BER tag
do_check_eq(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG);

Просмотреть файл

@ -72,7 +72,7 @@ add_test(function test_queryVoicePrivacyMode_success_enabled_true() {
let workerHelper = _getWorker();
let worker = workerHelper.worker;
worker.Buf.readUint32List = function fakeReadUint32List() {
worker.Buf.readInt32List = function fakeReadUint32List() {
return [1];
};
@ -95,7 +95,7 @@ add_test(function test_queryVoicePrivacyMode_success_enabled_false() {
let workerHelper = _getWorker();
let worker = workerHelper.worker;
worker.Buf.readUint32List = function fakeReadUint32List() {
worker.Buf.readInt32List = function fakeReadUint32List() {
return [0];
};

Просмотреть файл

@ -262,22 +262,22 @@ let Buf = {
return this.readUint8() | this.readUint8() << 8;
},
readUint32: function readUint32() {
readInt32: function readInt32() {
return this.readUint8() | this.readUint8() << 8 |
this.readUint8() << 16 | this.readUint8() << 24;
},
readUint32List: function readUint32List() {
let length = this.readUint32();
readInt32List: function readInt32List() {
let length = this.readInt32();
let ints = [];
for (let i = 0; i < length; i++) {
ints.push(this.readUint32());
ints.push(this.readInt32());
}
return ints;
},
readString: function readString() {
let string_len = this.readUint32();
let string_len = this.readInt32();
if (string_len < 0 || string_len >= this.INT32_MAX) {
return null;
}
@ -293,7 +293,7 @@ let Buf = {
},
readStringList: function readStringList() {
let num_strings = this.readUint32();
let num_strings = this.readInt32();
let strings = [];
for (let i = 0; i < num_strings; i++) {
strings.push(this.readString());
@ -349,7 +349,7 @@ let Buf = {
this.writeUint8((value >> 8) & 0xff);
},
writeUint32: function writeUint32(value) {
writeInt32: function writeInt32(value) {
this.writeUint8(value & 0xff);
this.writeUint8((value >> 8) & 0xff);
this.writeUint8((value >> 16) & 0xff);
@ -358,10 +358,10 @@ let Buf = {
writeString: function writeString(value) {
if (value == null) {
this.writeUint32(-1);
this.writeInt32(-1);
return;
}
this.writeUint32(value.length);
this.writeInt32(value.length);
for (let i = 0; i < value.length; i++) {
this.writeUint16(value.charCodeAt(i));
}
@ -372,7 +372,7 @@ let Buf = {
},
writeStringList: function writeStringList(strings) {
this.writeUint32(strings.length);
this.writeInt32(strings.length);
for (let i = 0; i < strings.length; i++) {
this.writeString(strings[i]);
}
@ -587,7 +587,7 @@ let Buf = {
* may call multiple read functions to extract data from the incoming buffer.
*/
//processParcel: function processParcel() {
// let something = this.readUint32();
// let something = this.readInt32();
// ...
//},

Просмотреть файл

@ -3337,11 +3337,11 @@ WifiWorker.prototype = {
this.queueRequest(false, function(data) {
if (this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED] ||
WifiManager.tetheringState != "UNINITIALIZED") {
this.disconnectedByWifi = true;
this.setWifiApEnabled(false, this.notifyTetheringOff.bind(this));
} else {
this.requestDone();
}
this.disconnectedByWifi = true;
}.bind(this));
}
@ -3366,11 +3366,11 @@ WifiWorker.prototype = {
if (enabled) {
this.queueRequest(false, function(data) {
if (WifiManager.enabled || WifiManager.state != "UNINITIALIZED") {
this.disconnectedByWifiTethering = true;
this.setWifiEnabled(false, this._setWifiEnabledCallback.bind(this));
} else {
this.requestDone();
}
this.disconnectedByWifiTethering = true;
}.bind(this));
}

Просмотреть файл

@ -189,7 +189,6 @@
"content/html/content/test/test_iframe_sandbox_plugins.html":"plugins not supported",
"content/html/content/test/test_object_plugin_nav.html":"plugins not supported",
"content/html/document/test/test_bug199692.html":"needs popup to be sized to 600*600",
"content/html/document/test/test_bug741266.html":"needs control of popup window size",
"docshell/test/navigation/test_popup-navigates-children.html":"Needs multiple window.open support, also uses docshelltreenode",
"docshell/test/test_bug590573.html":"queryinterfaces into webnavigation, might suffer from something similar as bug 823022",
@ -208,7 +207,6 @@
"content/base/test/csp/test_CSP_bug916446.html":"observer not working",
"content/base/test/test_CrossSiteXHR_origin.html":"https not working, bug 907770",
"content/base/test/test_bug326337.html":"popup windows don't have specialpowers installed, could be solved with sendmessage/receivemessage",
"content/base/test/test_plugin_freezing.html":"",
"content/base/test/test_bug466409.html":"",
"content/base/test/test_bug482935.html":"",

Просмотреть файл

@ -14,7 +14,20 @@ let container = homescreen.contentWindow.document.getElementById('test-container
function openWindow(aEvent) {
var popupIframe = aEvent.detail.frameElement;
popupIframe.setAttribute('style', 'position: absolute; left: 0; top: 300px; background: white; ');
popupIframe.setAttribute('style', 'position: absolute; left: 0; top: 0px; background: white;');
// This is to size the iframe to what is requested in the window.open call,
// e.g. window.open("", "", "width=600,height=600");
if (aEvent.detail.features.indexOf('width') != -1) {
let width = aEvent.detail.features.substr(aEvent.detail.features.indexOf('width')+6);
width = width.substr(0,width.indexOf(',') == -1 ? width.length : width.indexOf(','));
popupIframe.style.width = width + 'px';
}
if (aEvent.detail.features.indexOf('height') != -1) {
let height = aEvent.detail.features.substr(aEvent.detail.features.indexOf('height')+7);
height = height.substr(0, height.indexOf(',') == -1 ? height.length : height.indexOf(','));
popupIframe.style.height = height + 'px';
}
popupIframe.addEventListener('mozbrowserclose', function(e) {
container.parentNode.removeChild(popupIframe);
@ -26,6 +39,11 @@ function openWindow(aEvent) {
popupIframe.addEventListener('mozbrowserloadstart', function(e) {
popupIframe.focus();
let mm = popupIframe.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
mm.loadFrameScript(CHILD_LOGGER_SCRIPT, true);
mm.loadFrameScript(CHILD_SCRIPT_API, true);
mm.loadFrameScript(CHILD_SCRIPT, true);
mm.loadFrameScript('data:,attachSpecialPowersToWindow%28content%29%3B', true);
});
container.parentNode.appendChild(popupIframe);

Просмотреть файл

@ -1,4 +1,3 @@
#
# 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/.
@ -887,8 +886,13 @@ class Mochitest(MochitestUtilsMixin):
# create mozrunner instance and start the system under test process
self.lastTestSeen = self.test_name
startTime = datetime.now()
runner_cls = mozrunner.runners.get(mozinfo.info.get('appname', 'firefox'),
mozrunner.Runner)
# b2g desktop requires FirefoxRunner even though appname is b2g
if mozinfo.info.get('appname') == 'b2g' and mozinfo.info.get('toolkit') != 'gonk':
runner_cls = mozrunner.FirefoxRunner
else:
runner_cls = mozrunner.runners.get(mozinfo.info.get('appname', 'firefox'),
mozrunner.Runner)
runner = runner_cls(profile=self.profile,
binary=cmd,
cmdargs=args,

Просмотреть файл

@ -18,7 +18,6 @@ except ImportError:
here = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, here)
from b2gautomation import B2GDesktopAutomation
from runtests import Mochitest
from runtests import MochitestUtilsMixin
from runtests import MochitestOptions
@ -225,9 +224,9 @@ class B2GDeviceMochitest(B2GMochitest):
class B2GDesktopMochitest(B2GMochitest, Mochitest):
def __init__(self, automation, marionette, profile_data_dir):
def __init__(self, marionette, profile_data_dir):
B2GMochitest.__init__(self, marionette, out_of_process=False, profile_data_dir=profile_data_dir)
Mochitest.__init__(self, automation)
Mochitest.__init__(self)
def runMarionetteScript(self, marionette, test_script, test_script_args):
assert(marionette.wait_for_port())
@ -337,8 +336,6 @@ def run_remote_mochitests(parser, options):
sys.exit(retVal)
def run_desktop_mochitests(parser, options):
automation = B2GDesktopAutomation()
# create our Marionette instance
kwargs = {}
if options.marionette:
@ -346,9 +343,7 @@ def run_desktop_mochitests(parser, options):
kwargs['host'] = host
kwargs['port'] = int(port)
marionette = Marionette.getMarionetteOrExit(**kwargs)
automation.marionette = marionette
mochitest = B2GDesktopMochitest(automation, marionette, options.profile_data_dir)
mochitest = B2GDesktopMochitest(marionette, options.profile_data_dir)
# b2g desktop builds don't always have a b2g-bin file
if options.app[-4:] == '-bin':
@ -361,10 +356,6 @@ def run_desktop_mochitests(parser, options):
if options.desktop and not options.profile:
raise Exception("must specify --profile when specifying --desktop")
automation.setServerInfo(options.webServer,
options.httpPort,
options.sslPort,
options.webSocketPort)
sys.exit(mochitest.runTests(options, onLaunch=mochitest.startTests))
def main():