зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
4f9cad8a80
|
@ -9,106 +9,7 @@
|
|||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const name = window.location.pathname;
|
||||
|
||||
ok(mozIndexedDB.deleteDatabase, "deleteDatabase function should exist!");
|
||||
|
||||
let request = mozIndexedDB.open(name, 10);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
|
||||
ok(request instanceof IDBOpenDBRequest, "Expect an IDBOpenDBRequest");
|
||||
|
||||
let event = yield;
|
||||
|
||||
is(event.type, "upgradeneeded", "Expect an upgradeneeded event");
|
||||
ok(event instanceof IDBVersionChangeEvent, "Expect a versionchange event");
|
||||
|
||||
let db = event.target.result;
|
||||
db.createObjectStore("stuff");
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
|
||||
is(event.type, "success", "Expect a success event");
|
||||
is(event.target, request, "Event has right target");
|
||||
ok(event.target.result instanceof IDBDatabase, "Result should be a database");
|
||||
is(db.objectStoreNames.length, 1, "Expect an objectStore here");
|
||||
|
||||
let request = mozIndexedDB.open(name, 10);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
is(event.type, "success", "Expect a success event");
|
||||
is(event.target, request, "Event has right target");
|
||||
ok(event.target.result instanceof IDBDatabase, "Result should be a database");
|
||||
let db2 = event.target.result;
|
||||
is(db2.objectStoreNames.length, 1, "Expect an objectStore here");
|
||||
|
||||
var onversionchangecalled = false;
|
||||
|
||||
function closeDBs(event) {
|
||||
onversionchangecalled = true;
|
||||
ok(event instanceof IDBVersionChangeEvent, "expect a versionchange event");
|
||||
is(event.oldVersion, 10, "oldVersion should be 10");
|
||||
todo(event.newVersion, null, "newVersion should be null");
|
||||
db.close();
|
||||
db2.close();
|
||||
db.onversionchange = errorHandler;
|
||||
db2.onversionchange = errorHandler;
|
||||
};
|
||||
|
||||
// The IDB spec doesn't guarantee the order that onversionchange will fire
|
||||
// on the dbs.
|
||||
db.onversionchange = closeDBs;
|
||||
db2.onversionchange = closeDBs;
|
||||
|
||||
let request = mozIndexedDB.deleteDatabase(name);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
ok(request instanceof IDBOpenDBRequest, "Expect an IDBOpenDBRequest");
|
||||
|
||||
event = yield;
|
||||
ok(onversionchangecalled, "Expected versionchange events");
|
||||
is(event.type, "success", "expect a success event");
|
||||
is(event.target, request, "event has right target");
|
||||
is(event.target.result, null, "event should have no result");
|
||||
|
||||
let request = mozIndexedDB.open(name, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
is(event.target.result.version, 1, "DB has proper version");
|
||||
is(event.target.result.objectStoreNames.length, 0, "DB should have no object stores");
|
||||
|
||||
|
||||
let request = mozIndexedDB.deleteDatabase("thisDatabaseHadBetterNotExist");
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
ok(true, "deleteDatabase on a non-existent database succeeded");
|
||||
|
||||
let request = mozIndexedDB.open("thisDatabaseHadBetterNotExist");
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
ok(true, "after deleting a non-existent database, open should work");
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="unit/test_deleteDatabase.js"></script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
|
||||
</head>
|
||||
|
|
|
@ -24,6 +24,7 @@ TEST_FILES = \
|
|||
test_cursor_mutation.js \
|
||||
test_cursor_update_updates_indexes.js \
|
||||
test_cursors.js \
|
||||
test_deleteDatabase.js \
|
||||
test_event_source.js \
|
||||
test_getAll.js \
|
||||
test_global_data.js \
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var testGenerator = testSteps();
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const name = this.window ? window.location.pathname : "Splendid Test";
|
||||
|
||||
ok(mozIndexedDB.deleteDatabase, "deleteDatabase function should exist!");
|
||||
|
||||
let request = mozIndexedDB.open(name, 10);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
|
||||
ok(request instanceof IDBOpenDBRequest, "Expect an IDBOpenDBRequest");
|
||||
|
||||
let event = yield;
|
||||
|
||||
is(event.type, "upgradeneeded", "Expect an upgradeneeded event");
|
||||
ok(event instanceof IDBVersionChangeEvent, "Expect a versionchange event");
|
||||
|
||||
let db = event.target.result;
|
||||
db.createObjectStore("stuff");
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
|
||||
is(event.type, "success", "Expect a success event");
|
||||
is(event.target, request, "Event has right target");
|
||||
ok(event.target.result instanceof IDBDatabase, "Result should be a database");
|
||||
is(db.objectStoreNames.length, 1, "Expect an objectStore here");
|
||||
|
||||
let request = mozIndexedDB.open(name, 10);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
is(event.type, "success", "Expect a success event");
|
||||
is(event.target, request, "Event has right target");
|
||||
ok(event.target.result instanceof IDBDatabase, "Result should be a database");
|
||||
let db2 = event.target.result;
|
||||
is(db2.objectStoreNames.length, 1, "Expect an objectStore here");
|
||||
|
||||
var onversionchangecalled = false;
|
||||
|
||||
function closeDBs(event) {
|
||||
onversionchangecalled = true;
|
||||
ok(event instanceof IDBVersionChangeEvent, "expect a versionchange event");
|
||||
is(event.oldVersion, 10, "oldVersion should be 10");
|
||||
todo(event.newVersion, null, "newVersion should be null");
|
||||
db.close();
|
||||
db2.close();
|
||||
db.onversionchange = errorHandler;
|
||||
db2.onversionchange = errorHandler;
|
||||
};
|
||||
|
||||
// The IDB spec doesn't guarantee the order that onversionchange will fire
|
||||
// on the dbs.
|
||||
db.onversionchange = closeDBs;
|
||||
db2.onversionchange = closeDBs;
|
||||
|
||||
let request = mozIndexedDB.deleteDatabase(name);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
ok(request instanceof IDBOpenDBRequest, "Expect an IDBOpenDBRequest");
|
||||
|
||||
event = yield;
|
||||
ok(onversionchangecalled, "Expected versionchange events");
|
||||
is(event.type, "success", "expect a success event");
|
||||
is(event.target, request, "event has right target");
|
||||
ok(event.target.result === undefined, "event should have no result");
|
||||
|
||||
let request = mozIndexedDB.open(name, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
is(event.target.result.version, 1, "DB has proper version");
|
||||
is(event.target.result.objectStoreNames.length, 0, "DB should have no object stores");
|
||||
|
||||
|
||||
let request = mozIndexedDB.deleteDatabase("thisDatabaseHadBetterNotExist");
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
ok(true, "deleteDatabase on a non-existent database succeeded");
|
||||
|
||||
let request = mozIndexedDB.open("thisDatabaseHadBetterNotExist");
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
ok(true, "after deleting a non-existent database, open should work");
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
|
@ -14,6 +14,7 @@ tail =
|
|||
[test_cursor_mutation.js]
|
||||
[test_cursor_update_updates_indexes.js]
|
||||
[test_cursors.js]
|
||||
[test_deleteDatabase.js]
|
||||
[test_event_source.js]
|
||||
[test_getAll.js]
|
||||
[test_global_data.js]
|
||||
|
|
|
@ -318,6 +318,14 @@ SpdySession::RegisterStreamID(SpdyStream *stream)
|
|||
if (mNextStreamID >= kMaxStreamID)
|
||||
mShouldGoAway = true;
|
||||
|
||||
// integrity check
|
||||
if (mStreamIDHash.Get(result)) {
|
||||
LOG3((" New ID already present\n"));
|
||||
NS_ABORT_IF_FALSE(false, "New ID already present in mStreamIDHash");
|
||||
mShouldGoAway = true;
|
||||
return kDeadStreamID;
|
||||
}
|
||||
|
||||
mStreamIDHash.Put(result, stream);
|
||||
return result;
|
||||
}
|
||||
|
@ -330,6 +338,13 @@ SpdySession::AddStream(nsAHttpTransaction *aHttpTransaction,
|
|||
NS_ABORT_IF_FALSE(!mStreamTransactionHash.Get(aHttpTransaction),
|
||||
"AddStream duplicate transaction pointer");
|
||||
|
||||
// integrity check
|
||||
if (mStreamTransactionHash.Get(aHttpTransaction)) {
|
||||
LOG3((" New transaction already present\n"));
|
||||
NS_ABORT_IF_FALSE(false, "New transaction already present in hash");
|
||||
return false;
|
||||
}
|
||||
|
||||
aHttpTransaction->SetConnection(this);
|
||||
SpdyStream *stream = new SpdyStream(aHttpTransaction,
|
||||
this,
|
||||
|
@ -822,6 +837,59 @@ SpdySession::GenerateGoAway()
|
|||
FlushOutputQueue();
|
||||
}
|
||||
|
||||
// perform a bunch of integrity checks on the stream.
|
||||
// returns true if passed, false (plus LOG and ABORT) if failed.
|
||||
bool
|
||||
SpdySession::VerifyStream(SpdyStream *aStream, PRUint32 aOptionalID = 0)
|
||||
{
|
||||
// This is annoying, but at least it is O(1)
|
||||
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
||||
|
||||
if (!aStream)
|
||||
return true;
|
||||
|
||||
PRUint32 test = 0;
|
||||
|
||||
do {
|
||||
if (aStream->StreamID() == kDeadStreamID)
|
||||
break;
|
||||
|
||||
nsAHttpTransaction *trans = aStream->Transaction();
|
||||
|
||||
test++;
|
||||
if (!trans)
|
||||
break;
|
||||
|
||||
test++;
|
||||
if (mStreamTransactionHash.Get(trans) != aStream)
|
||||
break;
|
||||
|
||||
if (aStream->StreamID()) {
|
||||
SpdyStream *idStream = mStreamIDHash.Get(aStream->StreamID());
|
||||
|
||||
test++;
|
||||
if (idStream != aStream)
|
||||
break;
|
||||
|
||||
if (aOptionalID) {
|
||||
test++;
|
||||
if (idStream->StreamID() != aOptionalID)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// tests passed
|
||||
return true;
|
||||
} while (0);
|
||||
|
||||
LOG(("SpdySession %p VerifyStream Failure %p stream->id=0x%x "
|
||||
"optionalID=0x%x trans=%p test=%d\n",
|
||||
this, aStream, aStream->StreamID(),
|
||||
aOptionalID, aStream->Transaction(), test));
|
||||
NS_ABORT_IF_FALSE(false, "VerifyStream");
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SpdySession::CleanupStream(SpdyStream *aStream, nsresult aResult,
|
||||
rstReason aResetCode)
|
||||
|
@ -830,6 +898,11 @@ SpdySession::CleanupStream(SpdyStream *aStream, nsresult aResult,
|
|||
LOG3(("SpdySession::CleanupStream %p %p 0x%x %X\n",
|
||||
this, aStream, aStream->StreamID(), aResult));
|
||||
|
||||
if (!VerifyStream(aStream)) {
|
||||
LOG(("SpdySession::CleanupStream failed to verify stream\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aStream->RecvdFin() && aStream->StreamID()) {
|
||||
LOG3(("Stream had not processed recv FIN, sending RST code %X\n",
|
||||
aResetCode));
|
||||
|
@ -937,6 +1010,19 @@ SpdySession::HandleSynStream(SpdySession *self)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdySession::SetInputFrameDataStream(PRUint32 streamID)
|
||||
{
|
||||
mInputFrameDataStream = mStreamIDHash.Get(streamID);
|
||||
if (VerifyStream(mInputFrameDataStream, streamID))
|
||||
return NS_OK;
|
||||
|
||||
LOG(("SpdySession::SetInputFrameDataStream failed to verify 0x%X\n",
|
||||
streamID));
|
||||
mInputFrameDataStream = nsnull;
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SpdySession::HandleSynReply(SpdySession *self)
|
||||
{
|
||||
|
@ -961,9 +1047,14 @@ SpdySession::HandleSynReply(SpdySession *self)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LOG3(("SpdySession::HandleSynReply %p lookup via streamID in syn_reply.\n",
|
||||
self));
|
||||
PRUint32 streamID =
|
||||
PR_ntohl(reinterpret_cast<PRUint32 *>(self->mInputFrameBuffer.get())[2]);
|
||||
self->mInputFrameDataStream = self->mStreamIDHash.Get(streamID);
|
||||
nsresult rv = self->SetInputFrameDataStream(streamID);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (!self->mInputFrameDataStream) {
|
||||
LOG3(("SpdySession::HandleSynReply %p lookup streamID in syn_reply "
|
||||
"0x%X failed. NextStreamID = 0x%x", self, streamID,
|
||||
|
@ -975,7 +1066,7 @@ SpdySession::HandleSynReply(SpdySession *self)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = self->HandleSynReplyForValidStream();
|
||||
rv = self->HandleSynReplyForValidStream();
|
||||
if (rv == NS_ERROR_ILLEGAL_VALUE) {
|
||||
LOG3(("SpdySession::HandleSynReply %p PROTOCOL_ERROR detected 0x%X\n",
|
||||
self, streamID));
|
||||
|
@ -1085,10 +1176,17 @@ SpdySession::HandleRstStream(SpdySession *self)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
self->mInputFrameDataStream = self->mStreamIDHash.Get(streamID);
|
||||
nsresult rv = self->SetInputFrameDataStream(streamID);
|
||||
|
||||
if (!self->mInputFrameDataStream) {
|
||||
if (NS_FAILED(rv))
|
||||
LOG(("SpdySession::HandleRstStream %p lookup streamID for RST Frame "
|
||||
"0x%X failed reason = %d :: VerifyStream Failed\n", self, streamID,
|
||||
self->mDownstreamRstReason));
|
||||
|
||||
LOG3(("SpdySession::HandleRstStream %p lookup streamID for RST Frame "
|
||||
"0x%X failed", self, streamID));
|
||||
"0x%X failed reason = %d", self, streamID,
|
||||
self->mDownstreamRstReason));
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
|
@ -1553,7 +1651,12 @@ SpdySession::WriteSegments(nsAHttpSegmentWriter *writer,
|
|||
|
||||
PRUint32 streamID =
|
||||
PR_ntohl(reinterpret_cast<PRUint32 *>(mInputFrameBuffer.get())[0]);
|
||||
mInputFrameDataStream = mStreamIDHash.Get(streamID);
|
||||
rv = SetInputFrameDataStream(streamID);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("SpdySession::WriteSegments %p lookup streamID 0x%X failed. "
|
||||
"probably due to verification.\n", this, streamID));
|
||||
return rv;
|
||||
}
|
||||
if (!mInputFrameDataStream) {
|
||||
LOG3(("SpdySession::WriteSegments %p lookup streamID 0x%X failed. "
|
||||
"Next = 0x%x", this, streamID, mNextStreamID));
|
||||
|
@ -1595,6 +1698,9 @@ SpdySession::WriteSegments(nsAHttpSegmentWriter *writer,
|
|||
// mInputFrameDataStream is reset by ChangeDownstreamState
|
||||
SpdyStream *stream = mInputFrameDataStream;
|
||||
ResetDownstreamState();
|
||||
LOG3(("SpdySession::WriteSegments cleanup stream on recv of rst "
|
||||
"session=%p stream=%p 0x%X\n", this, stream,
|
||||
stream ? stream->StreamID() : 0));
|
||||
CleanupStream(stream, rv, RST_CANCEL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1602,6 +1708,11 @@ SpdySession::WriteSegments(nsAHttpSegmentWriter *writer,
|
|||
if (mDownstreamState == PROCESSING_DATA_FRAME ||
|
||||
mDownstreamState == PROCESSING_CONTROL_SYN_REPLY) {
|
||||
|
||||
// The cleanup stream should only be set while stream->WriteSegments is
|
||||
// on the stack and then cleaned up in this code block afterwards.
|
||||
NS_ABORT_IF_FALSE(!mNeedsCleanup, "cleanup stream set unexpectedly");
|
||||
mNeedsCleanup = nsnull; /* just in case */
|
||||
|
||||
mSegmentWriter = writer;
|
||||
rv = mInputFrameDataStream->WriteSegments(this, count, countWritten);
|
||||
mSegmentWriter = nsnull;
|
||||
|
@ -1614,12 +1725,21 @@ SpdySession::WriteSegments(nsAHttpSegmentWriter *writer,
|
|||
SpdyStream *stream = mInputFrameDataStream;
|
||||
if (mInputFrameDataRead == mInputFrameDataSize)
|
||||
ResetDownstreamState();
|
||||
LOG3(("SpdySession::WriteSegments session=%p stream=%p 0x%X "
|
||||
"needscleanup=%p. cleanup stream based on "
|
||||
"stream->writeSegments returning BASE_STREAM_CLOSED\n",
|
||||
this, stream, stream ? stream->StreamID() : 0,
|
||||
mNeedsCleanup));
|
||||
CleanupStream(stream, NS_OK, RST_CANCEL);
|
||||
NS_ABORT_IF_FALSE(!mNeedsCleanup, "double cleanup out of data frame");
|
||||
mNeedsCleanup = nsnull; /* just in case */
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mNeedsCleanup) {
|
||||
LOG3(("SpdySession::WriteSegments session=%p stream=%p 0x%X "
|
||||
"cleanup stream based on mNeedsCleanup.\n",
|
||||
this, mNeedsCleanup, mNeedsCleanup ? mNeedsCleanup->StreamID() : 0));
|
||||
CleanupStream(mNeedsCleanup, NS_OK, RST_CANCEL);
|
||||
mNeedsCleanup = nsnull;
|
||||
}
|
||||
|
@ -1946,7 +2066,7 @@ SpdySession::TransactionHasDataToWrite(nsAHttpTransaction *caller)
|
|||
// it is no longer blocked on read.
|
||||
|
||||
SpdyStream *stream = mStreamTransactionHash.Get(caller);
|
||||
if (!stream) {
|
||||
if (!stream || !VerifyStream(stream)) {
|
||||
LOG3(("SpdySession::TransactionHasDataToWrite %p caller %p not found",
|
||||
this, caller));
|
||||
return;
|
||||
|
|
|
@ -126,6 +126,10 @@ public:
|
|||
const static PRUint32 kDefaultMaxConcurrent = 100;
|
||||
const static PRUint32 kMaxStreamID = 0x7800000;
|
||||
|
||||
// This is a sentinel for a deleted stream. It is not a valid
|
||||
// 31 bit stream ID.
|
||||
const static PRUint32 kDeadStreamID = 0xffffdead;
|
||||
|
||||
static nsresult HandleSynStream(SpdySession *);
|
||||
static nsresult HandleSynReply(SpdySession *);
|
||||
static nsresult HandleRstStream(SpdySession *);
|
||||
|
@ -185,6 +189,8 @@ private:
|
|||
bool RoomForMoreConcurrent();
|
||||
void ActivateStream(SpdyStream *);
|
||||
void ProcessPending();
|
||||
nsresult SetInputFrameDataStream(PRUint32);
|
||||
bool VerifyStream(SpdyStream *, PRUint32);
|
||||
|
||||
// a wrapper for all calls to the nshttpconnection level segment writer. Used
|
||||
// to track network I/O for timeout purposes
|
||||
|
|
|
@ -60,6 +60,7 @@ SpdyStream::SpdyStream(nsAHttpTransaction *httpTransaction,
|
|||
|
||||
SpdyStream::~SpdyStream()
|
||||
{
|
||||
mStreamID = SpdySession::kDeadStreamID;
|
||||
}
|
||||
|
||||
// ReadSegments() is used to write data down the socket. Generally, HTTP
|
||||
|
|
|
@ -1179,7 +1179,7 @@ nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent)
|
|||
bool confirmedRestrict = false;
|
||||
for (PRUint32 index = 0; index < ent->mActiveConns.Length(); ++index) {
|
||||
nsHttpConnection *conn = ent->mActiveConns[index];
|
||||
if (!conn->ReportedNPN() || conn->EverUsedSpdy()) {
|
||||
if (!conn->ReportedNPN() || conn->CanDirectlyActivate()) {
|
||||
confirmedRestrict = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -4,4 +4,5 @@
|
|||
|
||||
from marionette import Marionette, HTMLElement
|
||||
from marionette_test import MarionetteTestCase
|
||||
from emulator import Emulator
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
from marionette import Marionette, Emulator
|
||||
from optparse import OptionParser
|
||||
|
||||
|
||||
def runemulator(homedir=None, url=None, pidfile=None, arch='x86'):
|
||||
qemu = Emulator(homedir=homedir, arch=arch)
|
||||
qemu.start()
|
||||
port = qemu.setup_port_forwarding(2828)
|
||||
assert(qemu.wait_for_port())
|
||||
if pidfile:
|
||||
f = open(pidfile, 'w')
|
||||
f.write("%d" % qemu.proc.pid)
|
||||
f.close()
|
||||
print 'emulator launched, pid:', qemu.proc.pid
|
||||
|
||||
if url:
|
||||
marionette = Marionette(port=port)
|
||||
marionette.start_session()
|
||||
marionette.navigate(url)
|
||||
marionette.delete_session()
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = OptionParser()
|
||||
parser.add_option('--repo', dest='repo_path', action='store',
|
||||
help='directory of the B2G repo')
|
||||
parser.add_option('--arch', dest='arch', action='store',
|
||||
default='x86',
|
||||
help='the emulator cpu architecture (x86 or arm)')
|
||||
parser.add_option('--url', dest='url', action='store',
|
||||
help='url to navigate to after launching emulator')
|
||||
parser.add_option('--pidfile', dest='pidfile', action='store',
|
||||
help='file in which to store emulator pid')
|
||||
|
||||
options, args = parser.parse_args()
|
||||
if not options.repo_path:
|
||||
raise Exception ("must specify the --repo /path/to/B2G/repo argument")
|
||||
|
||||
runemulator(homedir=options.repo_path,
|
||||
url=options.url,
|
||||
pidfile=options.pidfile,
|
||||
arch=options.arch)
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#!/bin/bash
|
||||
# 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/.
|
||||
|
||||
# Marionette requires Python 2.7, so the first parameter to this script
|
||||
# should be the path to that.
|
||||
PYTHON=$1
|
||||
|
||||
if [ -z "${PYTHON}" ]
|
||||
then
|
||||
echo "No python found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine the absolute path of our location.
|
||||
echo $0
|
||||
echo `dirname $0`
|
||||
echo $PWD
|
||||
SCRIPTS_HOME=`dirname $0`
|
||||
cd $SCRIPTS_HOME
|
||||
cd ..
|
||||
MARIONETTE_HOME=`dirname $PWD`
|
||||
echo "Detected Marionette home in $MARIONETTE_HOME"
|
||||
|
||||
# If a GECKO_OBJDIR environemnt variable exists, we will create the Python
|
||||
# virtual envirnoment there. Otherwise we create it in the PWD.
|
||||
VENV_DIR="runemu_venv"
|
||||
if [ -z $GECKO_OBJDIR ]
|
||||
then
|
||||
VENV_DIR="$MARIONETTE_HOME/$VENV_DIR"
|
||||
else
|
||||
VENV_DIR="$GECKO_OBJDIR/$VENV_DIR"
|
||||
fi
|
||||
|
||||
# Check if environment exists, if not, create a virtualenv:
|
||||
if [ -d $VENV_DIR ]
|
||||
then
|
||||
echo "Using virtual environment in $VENV_DIR"
|
||||
cd $VENV_DIR
|
||||
. bin/activate
|
||||
else
|
||||
echo "Creating a virtual environment in $VENV_DIR"
|
||||
curl https://raw.github.com/pypa/virtualenv/develop/virtualenv.py | ${PYTHON} - $VENV_DIR
|
||||
cd $VENV_DIR
|
||||
. bin/activate
|
||||
# set up mozbase
|
||||
git clone git://github.com/mozilla/mozbase.git
|
||||
cd mozbase
|
||||
python setup_development.py
|
||||
fi
|
||||
|
||||
# update the marionette_client
|
||||
cd $MARIONETTE_HOME
|
||||
python setup.py develop
|
||||
cd marionette
|
||||
|
||||
# pop off the python parameter
|
||||
shift
|
||||
cd scripts
|
||||
python runemu.py $@
|
||||
|
Загрузка…
Ссылка в новой задаче