Bug 1030442 - Be able to set and clear prefs at gecko startup, r=jgriffin

This commit is contained in:
Malini Das 2014-07-22 17:27:25 -04:00
Родитель b80dee55dd
Коммит 02111d8443
4 изменённых файлов: 137 добавлений и 3 удалений

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

@ -2,6 +2,9 @@
# 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 copy import deepcopy
import errno
import platform
import os
import time
@ -21,18 +24,21 @@ class GeckoInstance(object):
"browser.warnOnQuit": False}
def __init__(self, host, port, bin, profile, app_args=None, symbols_path=None,
gecko_log=None):
gecko_log=None, prefs=None):
self.marionette_host = host
self.marionette_port = port
self.bin = bin
self.profile_path = profile
self.prefs = prefs
self.app_args = app_args or []
self.runner = None
self.symbols_path = symbols_path
self.gecko_log = gecko_log
def start(self):
profile_args = {"preferences": self.required_prefs}
profile_args = {"preferences": deepcopy(self.required_prefs)}
if self.prefs:
profile_args["preferences"].update(self.prefs)
if not self.profile_path:
profile_args["restore"] = False
profile = Profile(**profile_args)
@ -48,7 +54,27 @@ class GeckoInstance(object):
self.gecko_log = os.path.realpath(self.gecko_log)
if os.access(self.gecko_log, os.F_OK):
os.remove(self.gecko_log)
if platform.system() is 'Windows':
# NOTE: windows has a weird filesystem where it happily 'closes'
# the file, but complains if you try to delete it. You get a
# 'file still in use' error. Sometimes you can wait a bit and
# a retry will succeed.
# If all retries fail, we'll just continue without removing
# the file. In this case, if we are restarting the instance,
# then the new logs just get appended to the old file.
tries = 0
while tries < 10:
try:
os.remove(self.gecko_log)
break
except WindowsError as e:
if e.errno == errno.EACCES:
tries += 1
time.sleep(0.5)
else:
raise e
else:
os.remove(self.gecko_log)
env = os.environ.copy()
@ -75,6 +101,13 @@ class GeckoInstance(object):
self.runner.stop()
self.runner.cleanup()
def restart(self, prefs=None):
self.close()
if prefs:
self.prefs = prefs
else:
self.prefs = None
self.start()
class B2GDesktopInstance(GeckoInstance):
required_prefs = {"focusmanager.testmode": True}

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

@ -4,6 +4,7 @@
import ConfigParser
import datetime
import json
import os
import socket
import StringIO
@ -702,6 +703,14 @@ class Marionette(object):
raise errors.MarionetteException(message=message, status=status, stacktrace=stacktrace)
raise errors.MarionetteException(message=response, status=500)
def _reset_timeouts(self):
if self.timeout is not None:
self.timeouts(self.TIMEOUT_SEARCH, self.timeout)
self.timeouts(self.TIMEOUT_SCRIPT, self.timeout)
self.timeouts(self.TIMEOUT_PAGE, self.timeout)
else:
self.timeouts(self.TIMEOUT_PAGE, 30000)
def check_for_crash(self):
returncode = None
name = None
@ -719,6 +728,64 @@ class Marionette(object):
(name, returncode))
return crashed
def enforce_gecko_prefs(self, prefs):
"""
Checks if the running instance has the given prefs. If not, it will kill the
currently running instance, and spawn a new instance with the requested preferences.
: param prefs: A dictionary whose keys are preference names.
"""
if not self.instance:
raise errors.MarionetteException("enforce_gecko_prefs can only be called " \
"on gecko instances launched by Marionette")
pref_exists = True
self.set_context(self.CONTEXT_CHROME)
for pref, value in prefs.iteritems():
if type(value) is not str:
value = json.dumps(value)
pref_exists = self.execute_script("""
let prefInterface = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
let pref = '%s';
let value = '%s';
let type = prefInterface.getPrefType(pref);
switch(type) {
case prefInterface.PREF_STRING:
return value == prefInterface.getCharPref(pref).toString();
case prefInterface.PREF_BOOL:
return value == prefInterface.getBoolPref(pref).toString();
case prefInterface.PREF_INT:
return value == prefInterface.getIntPref(pref).toString();
case prefInterface.PREF_INVALID:
return false;
}
""" % (pref, value))
if not pref_exists:
break
self.set_context(self.CONTEXT_CONTENT)
if not pref_exists:
self.delete_session()
self.instance.restart(prefs)
assert(self.wait_for_port()), "Timed out waiting for port!"
self.start_session()
self._reset_timeouts()
def restart_with_clean_profile(self):
"""
This will terminate the currently running instance, and spawn a new instance
with a clean profile.
: param prefs: A dictionary whose keys are preference names.
"""
if not self.instance:
raise errors.MarionetteException("enforce_gecko_prefs can only be called " \
"on gecko instances launched by Marionette")
self.delete_session()
self.instance.restart()
assert(self.wait_for_port()), "Timed out waiting for port!"
self.start_session()
self._reset_timeouts()
def absolute_url(self, relative_url):
'''
Returns an absolute url for files served from Marionette's www directory.

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

@ -0,0 +1,32 @@
# 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 os
from errors import JavascriptException
from marionette_test import MarionetteTestCase
class TestLog(MarionetteTestCase):
def setUp(self):
MarionetteTestCase.setUp(self)
self.marionette.enforce_gecko_prefs({"marionette.test.bool": True, "marionette.test.string": "testing", "marionette.test.int": 3})
def test_preferences_are_set(self):
bool_value = self.marionette.execute_script("return SpecialPowers.getBoolPref('marionette.test.bool');")
string_value = self.marionette.execute_script("return SpecialPowers.getCharPref('marionette.test.string');")
int_value = self.marionette.execute_script("return SpecialPowers.getIntPref('marionette.test.int');")
self.assertTrue(bool_value)
self.assertEqual(string_value, "testing")
self.assertEqual(int_value, 3)
def test_change_preset(self):
bool_value = self.marionette.execute_script("return SpecialPowers.getBoolPref('marionette.test.bool');")
self.assertTrue(bool_value)
self.marionette.enforce_gecko_prefs({"marionette.test.bool": False})
bool_value = self.marionette.execute_script("return SpecialPowers.getBoolPref('marionette.test.bool');")
self.assertFalse(bool_value)
def test_clean_profile(self):
self.marionette.restart_with_clean_profile()
with self.assertRaisesRegexp(JavascriptException, "Error getting pref"):
bool_value = self.marionette.execute_script("return SpecialPowers.getBoolPref('marionette.test.bool');")

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

@ -115,5 +115,7 @@ browser = false
[test_execute_isolate.py]
[test_click_scrolling.py]
[test_profile_management.py]
b2g = false
[include:oop/manifest.ini]