Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2013-05-16 11:26:58 -04:00
commit 015d7a6235
16 changed files with 90 additions and 635 deletions

View File

@ -188,6 +188,7 @@ let FormAssistant = {
addEventListener("beforeunload", this, true, false);
addEventListener("input", this, true, false);
addEventListener("keydown", this, true, false);
addEventListener("keyup", this, true, false);
addMessageListener("Forms:Select:Choice", this);
addMessageListener("Forms:Input:Value", this);
addMessageListener("Forms:Select:Blur", this);
@ -261,6 +262,7 @@ let FormAssistant = {
// current input field has changed.
EditAction: function fa_editAction() {
if (this._editing) {
this._editing = false;
return;
}
this.sendKeyboardState(this.focusedElement);
@ -359,12 +361,15 @@ let FormAssistant = {
this._editing = true;
// We use 'setTimeout' to wait until the input element accomplishes the
// change in selection range or text content.
// change in selection range.
content.setTimeout(function() {
this.updateSelection();
this._editing = false;
}.bind(this), 0);
break;
case "keyup":
this._editing = false;
break;
}
},

View File

@ -31,7 +31,9 @@ window.addEventListener('load', function() {
});
window.addEventListener('unload', function() {
Services.obs.removeObserver(runAppObj, 'browser-ui-startup-complete');
if (runAppObj) {
Services.obs.removeObserver(runAppObj, 'browser-ui-startup-complete');
}
});
function AppRunner(aName) {

View File

@ -611,6 +611,9 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
// don't keep trying to decode if the decoder doesn't want to.
return false;
}
else if (err != OK && err != -ETIMEDOUT) {
return false;
}
return true;
}
@ -664,6 +667,9 @@ bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
else if (err == UNKNOWN_ERROR) {
return false;
}
else if (err != OK && err != -ETIMEDOUT) {
return false;
}
return true;
}

View File

@ -17,7 +17,6 @@
#include "mozilla/Hal.h"
#include "AudioManager.h"
#include "android_audio/AudioSystem.h"
#include "nsIObserverService.h"
#include "mozilla/Services.h"
#include "AudioChannelService.h"
@ -36,6 +35,8 @@ using namespace mozilla;
#define HEADPHONES_STATUS_UNKNOWN NS_LITERAL_STRING("unknown").get()
#define BLUETOOTH_SCO_STATUS_CHANGED "bluetooth-sco-status-changed"
static void BinderDeadCallback(status_t aErr);
static void InternalSetAudioRoutes(SwitchState aState);
// Refer AudioService.java from Android
static int sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
5, // voice call
@ -51,9 +52,48 @@ static int sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
15, // FM
};
// A bitwise variable for recording what kind of headset is attached.
static int sHeadsetState;
static int sHeadsetState = SWITCH_STATE_OFF;
static int kBtSampleRate = 8000;
class RecoverTask : public nsRunnable
{
public:
RecoverTask() {}
NS_IMETHODIMP Run() {
nsCOMPtr<nsIAudioManager> am = do_GetService(NS_AUDIOMANAGER_CONTRACTID);
NS_ENSURE_TRUE(am, NS_OK);
for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(i), 0,
sMaxStreamVolumeTbl[i]);
int32_t volidx = 0;
am->GetStreamVolumeIndex(i, &volidx);
am->SetStreamVolumeIndex(static_cast<audio_stream_type_t>(i),
volidx);
}
if (sHeadsetState & AUDIO_DEVICE_OUT_WIRED_HEADSET)
InternalSetAudioRoutes(SWITCH_STATE_HEADSET);
else if (sHeadsetState & AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
InternalSetAudioRoutes(SWITCH_STATE_HEADPHONE);
else
InternalSetAudioRoutes(SWITCH_STATE_OFF);
int32_t phoneState = nsIAudioManager::PHONE_STATE_INVALID;
am->GetPhoneState(&phoneState);
AudioSystem::setPhoneState(phoneState);
AudioSystem::get_audio_flinger();
return NS_OK;
}
};
static void
BinderDeadCallback(status_t aErr)
{
if (aErr == DEAD_OBJECT) {
NS_DispatchToMainThread(new RecoverTask());
}
}
static bool
IsDeviceOn(audio_devices_t device)
{
@ -145,7 +185,7 @@ AudioManager::Observe(nsISupports* aSubject,
const PRUnichar* aData)
{
if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED)) {
if (aData) {
if (NS_strlen(aData) > 0) {
String8 cmd;
cmd.appendFormat("bt_samplerate=%d", kBtSampleRate);
AudioSystem::setParameters(0, cmd);
@ -214,10 +254,13 @@ AudioManager::AudioManager() : mPhoneState(PHONE_STATE_CURRENT),
for (int loop = 0; loop < AUDIO_STREAM_CNT; loop++) {
AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(loop), 0,
sMaxStreamVolumeTbl[loop]);
mCurrentStreamVolumeTbl[loop] = sMaxStreamVolumeTbl[loop];
}
// Force publicnotification to output at maximal volume
AudioSystem::setStreamVolumeIndex(static_cast<audio_stream_type_t>(AUDIO_STREAM_ENFORCED_AUDIBLE),
sMaxStreamVolumeTbl[AUDIO_STREAM_ENFORCED_AUDIBLE]);
AudioSystem::setErrorCallback(BinderDeadCallback);
}
AudioManager::~AudioManager() {
@ -225,7 +268,7 @@ AudioManager::~AudioManager() {
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_SCO_STATUS_CHANGED))) {
NS_WARNING("Failed to add bluetooth-sco-status-changed oberver!");
NS_WARNING("Failed to remove bluetooth-sco-status-changed oberver!");
}
}
@ -410,6 +453,7 @@ AudioManager::SetFmRadioAudioEnabled(bool aFmRadioAudioEnabled)
int32_t volIndex = 0;
AudioSystem::getStreamVolumeIndex(static_cast<audio_stream_type_t>(AUDIO_STREAM_MUSIC), &volIndex);
AudioSystem::setStreamVolumeIndex(static_cast<audio_stream_type_t>(AUDIO_STREAM_FM), volIndex);
mCurrentStreamVolumeTbl[AUDIO_STREAM_FM] = volIndex;
}
return NS_OK;
} else {
@ -425,16 +469,17 @@ AudioManager::SetStreamVolumeIndex(int32_t aStream, int32_t aIndex) {
// sync fm volume with music stream type
if (aStream == AUDIO_STREAM_MUSIC && IsDeviceOn(AUDIO_DEVICE_OUT_FM)) {
AudioSystem::setStreamVolumeIndex(static_cast<audio_stream_type_t>(AUDIO_STREAM_FM), aIndex);
mCurrentStreamVolumeTbl[AUDIO_STREAM_FM] = aIndex;
}
mCurrentStreamVolumeTbl[aStream] = aIndex;
return status ? NS_ERROR_FAILURE : NS_OK;
}
NS_IMETHODIMP
AudioManager::GetStreamVolumeIndex(int32_t aStream, int32_t* aIndex) {
status_t status =
AudioSystem::getStreamVolumeIndex(static_cast<audio_stream_type_t>(aStream), aIndex);
return status ? NS_ERROR_FAILURE : NS_OK;
*aIndex = mCurrentStreamVolumeTbl[aStream];
return NS_OK;
}
NS_IMETHODIMP

View File

@ -21,6 +21,7 @@
#include "nsIAudioManager.h"
#include "nsIObserver.h"
#include "AudioChannelAgent.h"
#include "android_audio/AudioSystem.h"
// {b2b51423-502d-4d77-89b3-7786b562b084}
#define NS_AUDIOMANAGER_CID {0x94f6fd70, 0x7615, 0x4af9, \
@ -51,6 +52,7 @@ public:
protected:
int32_t mPhoneState;
int mCurrentStreamVolumeTbl[AUDIO_STREAM_CNT];
private:
nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;

View File

@ -10170,10 +10170,7 @@ let ICCRecordHelper = {
", spnDisplayCondition = " + spnDisplayCondition);
}
RIL.iccInfoPrivate.SPN = {
spn : spn,
spnDisplayCondition : spnDisplayCondition,
};
RIL.iccInfoPrivate.spnDisplayCondition = spnDisplayCondition;
RIL.iccInfo.spn = spn;
ICCUtilsHelper.updateDisplayCondition();
ICCUtilsHelper.handleICCInfoChange();
@ -11138,11 +11135,11 @@ let ICCUtilsHelper = {
// isDisplaySpnRequired = false
let iccInfo = RIL.iccInfo;
let iccInfoPriv = RIL.iccInfoPrivate;
let iccSpn = iccInfoPriv.SPN;
let displayCondition = iccInfoPriv.spnDisplayCondition;
let origIsDisplayNetworkNameRequired = iccInfo.isDisplayNetworkNameRequired;
let origIsDisplaySPNRequired = iccInfo.isDisplaySpnRequired;
if (!iccSpn) {
if (displayCondition === undefined) {
iccInfo.isDisplayNetworkNameRequired = true;
iccInfo.isDisplaySpnRequired = false;
} else if (RIL._isCdma) {
@ -11153,9 +11150,9 @@ let ICCUtilsHelper = {
iccInfo.isDisplayNetworkNameRequired = false;
// If display condition is false, we don't even need to check network id
// If display condition is 0x0, we don't even need to check network id
// or system id.
if (iccSpn.spnDisplayCondition == false) {
if (displayCondition == 0x0) {
iccInfo.isDisplaySpnRequired = false;
} else {
// CDMA SPN Display condition dosen't specify whenever network name is
@ -11227,11 +11224,7 @@ let ICCUtilsHelper = {
// EF_SPDI contains a list of PLMNs in which the Service Provider Name
// shall be displayed.
iccInfo.isDisplaySpnRequired = true;
if (iccSpn.spnDisplayCondition & 0x01) {
iccInfo.isDisplayNetworkNameRequired = true;
} else {
iccInfo.isDisplayNetworkNameRequired = false;
}
iccInfo.isDisplayNetworkNameRequired = (displayCondition & 0x01) != 0;
} else {
// The second bit of display condition tells us if we should display
// registered PLMN.
@ -11240,13 +11233,8 @@ let ICCUtilsHelper = {
// We didn't found the requirement of displaying network name if
// current PLMN isn't HPLMN nor one of PLMN in SPDI. So we keep
// isDisplayNetworkNameRequired false.
if (iccSpn.spnDisplayCondition & 0x02) {
iccInfo.isDisplayNetworkNameRequired = false;
iccInfo.isDisplaySpnRequired = false;
} else {
iccInfo.isDisplayNetworkNameRequired = false;
iccInfo.isDisplaySpnRequired = true;
}
iccInfo.isDisplayNetworkNameRequired = false;
iccInfo.isDisplaySpnRequired = (displayCondition & 0x02) == 0;
}
}
@ -12069,9 +12057,7 @@ let RuimRecordHelper = {
debug("CDMA SPN: " + RIL.iccInfo.spn +
", Display condition: " + displayCondition);
}
RIL.iccInfoPrivate.SPN = {
spnDisplayCondition: displayCondition
};
RIL.iccInfoPrivate.spnDisplayCondition = displayCondition;
Buf.seekIncoming((octetLen - readLen) * PDU_HEX_OCTET_SIZE);
Buf.readStringDelimiter(strLen);
}

View File

@ -975,9 +975,7 @@ add_test(function test_spn_display_condition() {
expectedIsDisplayNetworkNameRequired,
expectedIsDisplaySPNRequired,
callback) {
RIL.iccInfoPrivate.SPN = {
spnDisplayCondition: iccDisplayCondition
};
RIL.iccInfoPrivate.spnDisplayCondition = iccDisplayCondition;
RIL.iccInfo = {
mcc: iccMcc,
mnc: iccMnc

View File

@ -143,7 +143,7 @@ add_test(function test_read_cdmaspn() {
worker.RuimRecordHelper.readSPN();
do_check_eq(worker.RIL.iccInfo.spn, expectedSpn);
do_check_eq(worker.RIL.iccInfoPrivate.SPN.spnDisplayCondition,
do_check_eq(worker.RIL.iccInfoPrivate.spnDisplayCondition,
expectedDisplayCondition);
}
@ -156,7 +156,7 @@ add_test(function test_read_cdmaspn() {
String.fromCharCode(0x592a) +
String.fromCharCode(0x96fb) +
String.fromCharCode(0x4fe1),
true);
0x1);
// Test when there's no tailing 0xff in spn string.
testReadSpn([0x01, 0x04, 0x06, 0x4e, 0x9e, 0x59, 0x2a, 0x96,
@ -165,7 +165,7 @@ add_test(function test_read_cdmaspn() {
String.fromCharCode(0x592a) +
String.fromCharCode(0x96fb) +
String.fromCharCode(0x4fe1),
true);
0x1);
run_next_test();
});
@ -199,9 +199,7 @@ add_test(function test_cdma_spn_display_condition() {
currentSystemId, currentNetworkId,
expectUpdateDisplayCondition,
expectIsDisplaySPNRequired) {
RIL.iccInfoPrivate.SPN = {
spnDisplayCondition: ruimDisplayCondition
};
RIL.iccInfoPrivate.spnDisplayCondition = ruimDisplayCondition;
RIL.cdmaHome = {
systemId: homeSystemIds,
networkId: homeNetworkIds
@ -217,16 +215,16 @@ add_test(function test_cdma_spn_display_condition() {
};
// SPN is not required when ruimDisplayCondition is false.
testDisplayCondition(false, [123], [345], 123, 345, true, false);
testDisplayCondition(0x0, [123], [345], 123, 345, true, false);
// System id and network id are all match.
testDisplayCondition(true, [123], [345], 123, 345, true, true);
testDisplayCondition(0x1, [123], [345], 123, 345, true, true);
// Network is 65535, we should only need to match system id.
testDisplayCondition(true, [123], [65535], 123, 345, false, true);
testDisplayCondition(0x1, [123], [65535], 123, 345, false, true);
// Not match.
testDisplayCondition(true, [123], [456], 123, 345, true, false);
testDisplayCondition(0x1, [123], [456], 123, 345, true, false);
run_next_test();
});

View File

@ -1,12 +0,0 @@
# 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]
es_server = buildbot-es.metrics.sjc1.mozilla.com:9200
rest_server = http://brasstacks.mozilla.com/autologserver/
[tests]
marionette = tests/unit-tests.ini
marionette-gaia = $homedir$/gaia/tests

View File

@ -1,222 +0,0 @@
# 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/.
# This function will run the pulse build watcher,
# then on detecting a build, it will run the tests
# using that build.
import ConfigParser
import json
import logging
import os
import sys
import traceback
import urllib
import mozlog
import shutil
from optparse import OptionParser
from threading import Thread, RLock
from manifestparser import TestManifest
from runtests import MarionetteTestRunner
from marionette import Marionette
from mozinstall import install
from mozillapulse.config import PulseConfiguration
from mozillapulse.consumers import GenericConsumer
class B2GPulseConsumer(GenericConsumer):
def __init__(self, **kwargs):
super(B2GPulseConsumer, self).__init__(PulseConfiguration(**kwargs),
'org.mozilla.exchange.b2g',
**kwargs)
class B2GAutomation:
def __init__(self, tests, testfile=None,
es_server=None, rest_server=None, testgroup='marionette'):
self.logger = mozlog.getLogger('B2G_AUTOMATION')
self.tests = tests
self.testfile = testfile
self.es_server = es_server
self.rest_server = rest_server
self.testgroup = testgroup
self.lock = RLock()
self.logger.info("Testlist: %s" % self.tests)
pulse = B2GPulseConsumer(applabel='b2g_build_listener')
pulse.configure(topic='#', callback=self.on_build)
if not self.testfile:
self.logger.info('waiting for pulse messages...')
pulse.listen()
else:
t = Thread(target=pulse.listen)
t.daemon = True
t.start()
f = open(self.testfile, 'r')
data = json.loads(f.read())
self.on_build(data, None)
def get_test_list(self, manifest):
self.logger.info("Reading test manifest: %s" % manifest)
mft = TestManifest()
mft.read(manifest)
# In the future if we want to add in more processing to the manifest
# here is where you'd do that. Right now, we just return a list of
# tests
testlist = []
for i in mft.active_tests(exists=False, disabled=False):
testlist.append(i["path"])
return testlist
def on_build(self, data, msg):
# Found marionette build! Install it
if msg is not None:
msg.ack()
self.lock.acquire()
try:
self.logger.info("got pulse message! %s" % repr(data))
if "buildurl" in data["payload"]:
directory = self.install_build(data['payload']['buildurl'])
rev = data["payload"]["commit"]
if directory == None:
self.logger.info("Failed to return build directory")
else:
self.run_marionette(directory, rev)
self.cleanup(directory)
else:
self.logger.error("Failed to find buildurl in msg, not running test")
except:
self.logger.exception("error while processing build")
self.lock.release()
# Download the build and untar it, return the directory it untared to
def install_build(self, url):
try:
self.logger.info("Installing build from url: %s" % url)
buildfile = os.path.abspath("b2gtarball.tar.gz")
urllib.urlretrieve(url, buildfile)
except:
self.logger.exception("Failed to download build")
try:
self.logger.info("Untarring build")
# Extract to the same local directory where we downloaded the build
# to. This defaults to the local directory where our script runs
dest = os.path.join(os.path.dirname(buildfile), 'downloadedbuild')
if (os.access(dest, os.F_OK)):
shutil.rmtree(dest)
install(buildfile, dest)
# This should extract into a qemu directory
qemu = os.path.join(dest, 'qemu')
if os.path.exists(qemu):
return qemu
else:
return None
except:
self.logger.exception("Failed to untar file")
return None
def run_marionette(self, dir, rev):
self.logger.info("Starting test run for revision: %s" % rev)
runner = MarionetteTestRunner(emulator=True,
homedir=dir,
autolog=True,
revision=rev,
logger=self.logger,
es_server=self.es_server,
rest_server=self.rest_server,
testgroup=self.testgroup)
for test in self.tests:
manifest = test[1].replace('$homedir$', os.path.dirname(dir))
testgroup = test[0]
runner.testgroup = testgroup
runner.run_tests([manifest], 'b2g')
def cleanup(self, dir):
self.logger.info("Cleaning up")
if os.path.exists("b2gtarball.tar.gz"):
os.remove("b2gtarball.tar.gz")
if os.path.exists(dir):
shutil.rmtree(dir)
def main():
parser = OptionParser(usage="%prog <options>")
parser.add_option("--config", action="store", dest="config_file",
default="automation.conf",
help="Specify the configuration file")
parser.add_option("--testfile", action="store", dest="testfile",
help = "Start in test mode without using pulse, "
"utilizing the pulse message defined in the specified file")
parser.add_option("--test-manifest", action="store", dest="testmanifest",
default = os.path.join("tests","unit-tests.ini"),
help="Specify the test manifest, defaults to tests/all-tests.ini")
parser.add_option("--log-file", action="store", dest="logfile",
default="b2gautomation.log",
help="Log file to store results, defaults to b2gautomation.log")
LOG_LEVELS = ("DEBUG", "INFO", "WARNING", "ERROR")
LEVEL_STRING = ", ".join(LOG_LEVELS)
parser.add_option("--log-level", action="store", type="choice",
dest="loglevel", default="DEBUG", choices=LOG_LEVELS,
help = "One of %s for logging level, defaults to debug" % LEVEL_STRING)
options, args = parser.parse_args()
cfg = ConfigParser.ConfigParser()
cfg.read(options.config_file)
try:
es_server = cfg.get('marionette', 'es_server')
except:
# let mozautolog provide the default
es_server = None
try:
rest_server = cfg.get('marionette', 'rest_server')
except:
# let mozautolog provide the default
rest_server = None
try:
tests = cfg.items('tests')
except:
tests = [('marionette', options.testmanifest)]
if not options.testmanifest:
parser.print_usage()
parser.exit()
if not os.path.exists(options.testmanifest):
print "Could not find manifest file: %s" % options.testmanifest
parser.print_usage()
parser.exit()
# Set up the logger
if os.path.exists(options.logfile):
os.remove(options.logfile)
logger = mozlog.getLogger("B2G_AUTOMATION", options.logfile)
if options.loglevel:
logger.setLevel(getattr(mozlog, options.loglevel, "DEBUG"))
logger.addHandler(logging.StreamHandler())
try:
b2gauto = B2GAutomation(tests,
testfile=options.testfile,
es_server=es_server,
rest_server=rest_server)
except:
s = traceback.format_exc()
logger.error(s)
return 1
return 0
if __name__ == "__main__":
main()

View File

@ -1,72 +0,0 @@
# 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/.
from git import *
from optparse import OptionParser
import os
import sys
def updategaia(repopath):
b2g = Repo(repopath)
gaia = Repo(os.path.join(repopath, 'gaia'))
gaia_submodule = None
for submodule in b2g.submodules:
if 'gaia' in submodule.name:
gaia_submodule = submodule
assert(gaia_submodule)
gaia_submodule_commit = gaia_submodule.hexsha
print 'gaia_submodule_commit', gaia_submodule_commit
gaia.heads.master.checkout()
print 'pulling from gaia origin/master'
gaia.remotes.origin.pull('master')
gaia_new_head = gaia.heads.master.commit.hexsha
print 'gaia_new_head', gaia_new_head
if gaia_submodule_commit == gaia_new_head:
print 'no change, exiting with code 10'
sys.exit(10)
def commitgaia(repopath):
b2g = Repo(repopath)
gaia = Repo(os.path.join(repopath, 'gaia'))
gaia_submodule = None
for submodule in b2g.submodules:
if 'gaia' in submodule.name:
gaia_submodule = submodule
assert(gaia_submodule)
gaia_submodule.binsha = gaia_submodule.module().head.commit.binsha
b2g.index.add([gaia_submodule])
commit = b2g.index.commit('Update gaia')
print 'pushing to B2G origin/master'
b2g.remotes.origin.push(b2g.head.reference)
print 'done!'
if __name__ == '__main__':
parser = OptionParser(usage='%prog [options]')
parser.add_option("--repo",
action = "store", dest = "repo",
help = "path to B2G repo")
parser.add_option("--updategaia",
action = "store_true", dest = "updategaia",
help = "update the Gaia submodule to HEAD")
parser.add_option("--commitgaia",
action = "store_true", dest = "commitgaia",
help = "commit current Gaia submodule HEAD")
options, tests = parser.parse_args()
if not options.repo:
raise 'must specify --repo /path/to/B2G'
if options.updategaia:
updategaia(options.repo)
elif options.commitgaia:
commitgaia(options.repo)
else:
raise 'No command specified'

View File

@ -1,13 +0,0 @@
# 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/.
from marionette import Marionette, HTMLElement
if __name__ == '__main__':
# launch Fennec with Marionette before starting this test!
m = Marionette(host='localhost', port=2828)
assert(m.start_session())
assert(10 == m.execute_script('return 10;'))

View File

@ -1,65 +0,0 @@
# 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/.
import threading
from testserver import TestServer
from marionette import Marionette, HTMLElement
if __name__ == '__main__':
# start the test server
server = TestServer(2626)
thread = threading.Thread(target=server.run)
thread.daemon = True
thread.start()
# run some trivial unit tests which just verify the protocol
m = Marionette(host='localhost', port=2626)
assert(m.status()['os']['arch'] == 'x86')
assert(m.start_session())
assert(m.get_session_capabilities()['javascriptEnabled'] == True)
assert(m.current_window_handle == server.TEST_CURRENT_WINDOW)
assert(m.window == server.TEST_CURRENT_WINDOW)
assert(m.window_handles == server.TEST_WINDOW_LIST)
assert(m.switch_to_window('window2'))
assert(m.window == 'window2')
assert(m.close_window('window2'))
assert(m.set_script_timeout(1000))
assert(m.set_search_timeout(500))
assert(m.get_url() == server.TEST_URL)
assert(m.navigate(server.TEST_URL))
assert(m.go_back())
assert(m.go_forward())
assert(m.refresh())
assert(m.execute_script(server.TEST_EXECUTE_SCRIPT))
assert(m.execute_js_script(server.TEST_EXECUTE_SCRIPT))
assert(m.execute_js_script(server.TEST_EXECUTE_SCRIPT, server.TEST_EXECUTE_SCRIPT_ARGS))
assert(m.execute_script(server.TEST_EXECUTE_SCRIPT, server.TEST_EXECUTE_SCRIPT_ARGS))
assert(m.execute_async_script(server.TEST_EXECUTE_SCRIPT))
assert(m.execute_async_script(server.TEST_EXECUTE_SCRIPT, server.TEST_EXECUTE_SCRIPT_ARGS))
assert(str(m.find_element(HTMLElement.CLASS, 'heading')) == server.TEST_FIND_ELEMENT)
assert([str(x) for x in m.find_elements(HTMLElement.TAG, 'p')] == server.TEST_FIND_ELEMENTS)
assert(str(m.find_element(HTMLElement.CLASS, 'heading').find_element(HTMLElement.TAG, 'h1')) == server.TEST_FIND_ELEMENT)
assert([str(x) for x in m.find_element(HTMLElement.ID, 'div1').find_elements(HTMLElement.SELECTOR, '.main')] == \
server.TEST_FIND_ELEMENTS)
assert(m.find_element(HTMLElement.ID, 'id1').click())
assert(m.find_element(HTMLElement.ID, 'id2').text() == server.TEST_GET_TEXT)
assert(m.find_element(HTMLElement.ID, 'id3').send_keys('Mozilla Firefox'))
assert(m.find_element(HTMLElement.ID, 'id3').value() == server.TEST_GET_VALUE)
assert(m.find_element(HTMLElement.ID, 'id3').clear())
assert(m.find_element(HTMLElement.ID, 'id3').is_selected())
assert(m.find_element(HTMLElement.ID, 'id1').equals(m.find_element(HTMLElement.TAG, 'p')))
assert(m.find_element(HTMLElement.ID, 'id3').is_enabled())
assert(m.find_element(HTMLElement.ID, 'id3').displayed())
assert(m.find_element(HTMLElement.ID, 'id3').get_attribute('value') == server.TEST_GET_VALUE)
assert(m.delete_session())
# verify a session is started automatically for us if needed
assert(m.switch_to_frame('frame1'))
assert(m.switch_to_frame(1))
assert(m.switch_to_frame(m.find_element(HTMLElement.ID, 'frameid')))
assert(m.switch_to_frame())
assert(m.current_window_handle == server.TEST_CURRENT_WINDOW)
assert(m.set_context(m.CONTEXT_CHROME))
assert(m.delete_session())

View File

@ -1,203 +0,0 @@
# 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/.
import json
import select
import socket
class TestServer(object):
""" A test Marionette server which can be used to test the Marionette
protocol. Each request will trigger a canned response; see
process_command().
"""
TEST_URL = 'http://www.mozilla.org'
TEST_CURRENT_WINDOW = 'window1'
TEST_WINDOW_LIST = ['window1', 'window2', 'window3']
TEST_EXECUTE_RETURN_VALUE = 10
TEST_EXECUTE_SCRIPT = 'return 2 * 5;'
TEST_EXECUTE_SCRIPT_ARGS = 'testing'
TEST_FIND_ELEMENT = 'element1'
TEST_FIND_ELEMENTS = ['element1', 'element2', 'element3']
TEST_GET_TEXT = 'first name'
TEST_GET_VALUE = 'Mozilla Firefox'
# canned responses for test messages
test_responses = {
'newSession': { 'value': 'a65bef90b145' },
'getMarionetteID': { 'id': 'conn0.marionette' },
'deleteSession': { 'ok': True },
'setScriptTimeout': { 'ok': True },
'setSearchTimeout': { 'ok': True },
'getWindow': { 'value': TEST_CURRENT_WINDOW },
'getWindows': { 'values': TEST_WINDOW_LIST },
'closeWindow': { 'ok': True },
'switchToWindow': { 'ok': True },
'switchToFrame': { 'ok': True },
'setContext': { 'ok': True },
'getUrl' : { 'value': TEST_URL },
'goUrl': { 'ok': True },
'goBack': { 'ok': True },
'goForward': { 'ok': True },
'refresh': { 'ok': True },
'executeScript': { 'value': TEST_EXECUTE_RETURN_VALUE },
'executeAsyncScript': { 'value': TEST_EXECUTE_RETURN_VALUE },
'executeJSScript': { 'value': TEST_EXECUTE_RETURN_VALUE },
'findElement': { 'value': TEST_FIND_ELEMENT },
'findElements': { 'values': TEST_FIND_ELEMENTS },
'clickElement': { 'ok': True },
'getElementText': { 'value': TEST_GET_TEXT },
'sendKeysToElement': { 'ok': True },
'clearElement': { 'ok': True },
'isElementSelected': { 'value': True },
'elementsEqual': { 'value': True },
'isElementEnabled': { 'value': True },
'isElementDisplayed': { 'value': True },
'getElementAttribute': { 'value': TEST_GET_VALUE },
'getSessionCapabilities': { 'value': {
"cssSelectorsEnabled": True,
"browserName": "firefox",
"handlesAlerts": True,
"javascriptEnabled": True,
"nativeEvents": True,
"platform": 'linux',
"takeScreenshot": False,
"version": "10.1"
}
},
'getStatus': { 'value': {
"os": {
"arch": "x86",
"name": "linux",
"version": "unknown"
},
"build": {
"revision": "unknown",
"time": "unknown",
"version": "unknown"
}
}
}
}
# canned error responses for test messages
error_responses = {
'executeScript': { 'error': { 'message': 'JavaScript error', 'status': 17 } },
'executeAsyncScript': { 'error': { 'message': 'Script timed out', 'status': 28 } },
'findElement': { 'error': { 'message': 'Element not found', 'status': 7 } },
'findElements': { 'error': { 'message': 'XPath is invalid', 'status': 19 } },
'closeWindow': { 'error': { 'message': 'No such window', 'status': 23 } },
'getWindow': { 'error': { 'message': 'No such window', 'status': 23 } },
'clickElement': { 'error': { 'message': 'Element no longer exists', 'status': 10 } },
'sendKeysToElement': { 'error': { 'message': 'Element is not visible on the page', 'status': 11 } },
'switchToFrame': { 'error': { 'message': 'No such frame', 'status': 8 } }
}
def __init__(self, port):
self.port = port
self.srvsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.srvsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.srvsock.bind(("", port))
self.srvsock.listen(5)
self.descriptors = [self.srvsock]
self.responses = self.test_responses
print 'TestServer started on port %s' % port
def _recv_n_bytes(self, sock, n):
""" Convenience method for receiving exactly n bytes from
self.sock (assuming it's open and connected).
"""
data = ''
while len(data) < n:
chunk = sock.recv(n - len(data))
if chunk == '':
break
data += chunk
return data
def receive(self, sock):
""" Receive the next complete response from the server, and return
it as a dict. Each response from the server is prepended by
len(message) + ':'.
"""
assert(sock)
response = sock.recv(10)
sep = response.find(':')
if sep == -1:
return None
length = response[0:sep]
response = response[sep + 1:]
response += self._recv_n_bytes(sock, int(length) + 1 + len(length) - 10)
print 'received', response
return json.loads(response)
def send(self, sock, msg):
print 'msg', msg
data = json.dumps(msg)
print 'sending %s' % data
sock.send('%s:%s' % (len(data), data))
def accept_new_connection(self):
newsock, (remhost, remport) = self.srvsock.accept()
self.descriptors.append( newsock )
str = 'Client connected %s:%s\r\n' % (remhost, remport)
print str
self.send(newsock, {'from': 'root',
'applicationType': 'gecko',
'traits': []})
def process_command(self, data):
command = data['type']
if command == 'use_test_responses':
self.responses = self.test_responses
return { 'ok': True }
elif command == 'use_error_responses':
self.responses = self.error_responses
return { 'ok': True }
if command in self.responses:
response = self.responses[command]
else:
response = { 'error': { 'message': 'unknown command: %s' % command, 'status': 500} }
if command not in ('newSession', 'getStatus', 'getMarionetteID') and 'session' not in data:
response = { 'error': { 'message': 'no session specified', 'status': 500 } }
return response
def run(self):
while 1:
# Await an event on a readable socket descriptor
(sread, swrite, sexc) = select.select( self.descriptors, [], [] )
# Iterate through the tagged read descriptors
for sock in sread:
# Received a connect to the server (listening) socket
if sock == self.srvsock:
self.accept_new_connection()
else:
# Received something on a client socket
try:
data = self.receive(sock)
except:
data = None
# Check to see if the peer socket closed
if data is None:
host,port = sock.getpeername()
str = 'Client disconnected %s:%s\r\n' % (host, port)
print str
sock.close
self.descriptors.remove(sock)
else:
if 'type' in data:
msg = self.process_command(data)
else:
msg = 'command: %s' % json.dumps(data)
self.send(sock, msg)
if __name__ == "__main__":
server = TestServer(2626)
server.run()

View File

@ -184,7 +184,6 @@
"dom/browser-element/mochitest/test_browserElement_inproc_CloseApp.html":"",
"dom/browser-element/mochitest/test_browserElement_inproc_CloseFromOpener.html":"",
"dom/browser-element/":"",
"dom/contacts/":"",
"dom/devicestorage/test/test_basic.html":"",
"dom/devicestorage/test/test_lastModificationFilter.html":"",

View File

@ -451,7 +451,8 @@ Java_org_mozilla_gecko_GeckoSmsManager_notifySmsDeleted(JNIEnv* jenv, jclass,
AndroidBridge::Bridge()->DequeueSmsRequest(mRequestId);
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
request->NotifyMessageDeleted(mDeleted);
// For android, we support only single SMS deletion.
request->NotifyMessageDeleted(&mDeleted, 1);
return NS_OK;
}