示例#1
0
 def setup(self):
     I18nSetup.locale_path = os.path.join(site.getsitepackages()[0], 'OWDTestToolkit/locale')
     if not I18nSetup.configured:
         marionette = Marionette()
         marionette.start_session()
         # Configure the translation to be used based on the previously retrieved language. Should
         # the translation is not found, the fallback will prevent a failure
         lang = marionette.execute_script("""return window.navigator.language;""")
         translation = gettext.translation('default', I18nSetup.locale_path, languages=[lang], fallback=True)
         I18nSetup._ = translation.ugettext
         I18nSetup.configured = True
     return I18nSetup._
示例#2
0
def test_load_vapid_page():
    client = Marionette('localhost', port=2828)
    client.start_session()
    url = 'https://jrconlin.github.io/Webpush_QA/'
    client.navigate(url)
    sleep(5)

    # Loop through each expected test element and make sure we have our unicode check mark
    field_ids = ['pre', 'reg', 'sub', 'gen', 'vap', 'enc', 'snd', 'rcv', 'dec']
    command = "return window.getComputedStyle(document.querySelector('li#{0}.done.undone'),':before').getPropertyValue('content')"

    for field_id in field_ids:
        resp = client.execute_script(command.format(field_id))
        assert resp == u'"\u2611"'
示例#3
0
class B2GDesktopReftest(RefTest):
    build_type = "desktop"
    marionette = None

    def __init__(self, marionette_args):
        RefTest.__init__(self)
        self.last_test = os.path.basename(__file__)
        self.marionette_args = marionette_args
        self.profile = None
        self.runner = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.timeout = None

    def run_marionette_script(self):
        self.marionette = Marionette(**self.marionette_args)
        assert(self.marionette.wait_for_port())
        self.marionette.start_session()
        if self.build_type == "mulet":
            self._wait_for_homescreen(timeout=300)
            self._unlockScreen()
        self.marionette.set_context(self.marionette.CONTEXT_CHROME)

        if os.path.isfile(self.test_script):
            f = open(self.test_script, 'r')
            self.test_script = f.read()
            f.close()
        self.marionette.execute_script(self.test_script)

    def run_tests(self, tests, options):
        manifests = self.resolver.resolveManifests(options, tests)

        self.profile = self.create_profile(options, manifests,
                                           profile_to_clone=options.profile)
        env = self.buildBrowserEnv(options, self.profile.profile)
        kp_kwargs = { 'processOutputLine': [self._on_output],
                      'onTimeout': [self._on_timeout],
                      'kill_on_timeout': False }

        if not options.debugger:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            self.timeout = options.timeout + 30.0

        log.info("%s | Running tests: start.", os.path.basename(__file__))
        cmd, args = self.build_command_line(options.app,
                            ignore_window_size=options.ignoreWindowSize,
                            browser_arg=options.browser_arg)
        self.runner = FirefoxRunner(profile=self.profile,
                                    binary=cmd,
                                    cmdargs=args,
                                    env=env,
                                    process_class=ProcessHandler,
                                    process_args=kp_kwargs,
                                    symbols_path=options.symbolsPath)

        status = 0
        try:
            self.runner.start(outputTimeout=self.timeout)
            log.info("%s | Application pid: %d",
                     os.path.basename(__file__),
                     self.runner.process_handler.pid)

            # kick starts the reftest harness
            self.run_marionette_script()
            status = self.runner.wait()
        finally:
            self.runner.check_for_crashes(test_name=self.last_test)
            self.runner.cleanup()

        if status > 0:
            log.testFail("%s | application terminated with exit code %s",
                         self.last_test, status)
        elif status < 0:
            log.info("%s | application killed with signal %s",
                         self.last_test, -status)

        log.info("%s | Running tests: end.", os.path.basename(__file__))
        return status

    def create_profile(self, options, manifests, profile_to_clone=None):
        profile = RefTest.createReftestProfile(self, options, manifests,
                                               profile_to_clone=profile_to_clone)

        prefs = {}
        # Turn off the locale picker screen
        prefs["browser.firstrun.show.localepicker"] = False
        if not self.build_type == "mulet":
            # FIXME: With Mulet we can't set this values since Gaia won't launch
            prefs["b2g.system_startup_url"] = \
                    "app://test-container.gaiamobile.org/index.html"
            prefs["b2g.system_manifest_url"] = \
                    "app://test-container.gaiamobile.org/manifest.webapp"
        # Make sure we disable system updates
        prefs["app.update.enabled"] = False
        prefs["app.update.url"] = ""
        prefs["app.update.url.override"] = ""
        # Disable webapp updates
        prefs["webapps.update.enabled"] = False
        # Disable tiles also
        prefs["browser.newtabpage.directory.source"] = ""
        prefs["browser.newtabpage.directory.ping"] = ""
        prefs["dom.ipc.tabs.disabled"] = False
        prefs["dom.mozBrowserFramesEnabled"] = True
        prefs["font.size.inflation.emPerLine"] = 0
        prefs["font.size.inflation.minTwips"] = 0
        prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org"
        prefs["reftest.browser.iframe.enabled"] = False
        prefs["reftest.remote"] = False
        # Set a future policy version to avoid the telemetry prompt.
        prefs["toolkit.telemetry.prompted"] = 999
        prefs["toolkit.telemetry.notifiedOptOut"] = 999
        # Disable periodic updates of service workers
        prefs["dom.serviceWorkers.periodic-updates.enabled"] = False

        # Set the extra prefs.
        profile.set_preferences(prefs)
        return profile

    def build_command_line(self, app, ignore_window_size=False,
                           browser_arg=None):
        cmd = os.path.abspath(app)
        args = ['-marionette']

        if browser_arg:
            args += [browser_arg]

        if not ignore_window_size:
            args.extend(['--screen', '800x1000'])

        if self.build_type == "mulet":
            args += ['-chrome', 'chrome://b2g/content/shell.html']
        return cmd, args

    def _on_output(self, line):
        sys.stdout.write("%s\n" % line)
        sys.stdout.flush()

        # TODO use structured logging
        if "TEST-START" in line and "|" in line:
            self.last_test = line.split("|")[1].strip()

    def _on_timeout(self):
        msg = "%s | application timed out after %s seconds with no output"
        log.testFail(msg % (self.last_test, self.timeout))

        # kill process to get a stack
        self.runner.stop(sig=signal.SIGABRT)
    def run_tests(self):
        """
        Generate the PGO profile data
        """
        from mozhttpd import MozHttpd
        from mozprofile import Preferences
        from mozdevice import ADBDevice, ADBTimeoutError
        from six import string_types
        from marionette_driver.marionette import Marionette

        app = self.query_package_name()

        IP = '10.0.2.2'
        PORT = 8888

        PATH_MAPPINGS = {
            '/js-input/webkit/PerformanceTests':
            'third_party/webkit/PerformanceTests',
        }

        dirs = self.query_abs_dirs()
        topsrcdir = os.path.join(dirs['abs_work_dir'], 'src')
        adb = self.query_exe('adb')

        path_mappings = {
            k: os.path.join(topsrcdir, v)
            for k, v in PATH_MAPPINGS.items()
        }
        httpd = MozHttpd(port=PORT,
                         docroot=os.path.join(topsrcdir, "build", "pgo"),
                         path_mappings=path_mappings)
        httpd.start(block=False)

        profile_data_dir = os.path.join(topsrcdir, 'testing', 'profiles')
        with open(os.path.join(profile_data_dir, 'profiles.json'), 'r') as fh:
            base_profiles = json.load(fh)['profileserver']

        prefpaths = [
            os.path.join(profile_data_dir, profile, 'user.js')
            for profile in base_profiles
        ]

        prefs = {}
        for path in prefpaths:
            prefs.update(Preferences.read_prefs(path))

        interpolation = {
            "server": "%s:%d" % httpd.httpd.server_address,
            "OOP": "false"
        }
        for k, v in prefs.items():
            if isinstance(v, string_types):
                v = v.format(**interpolation)
            prefs[k] = Preferences.cast(v)

        # Enforce 1proc. This isn't in one of the user.js files because those
        # are shared with desktop, which wants e10s. We can't interpolate
        # because the formatting code only works for strings, and this is a
        # bool pref.
        prefs["browser.tabs.remote.autostart"] = False

        outputdir = self.config.get('output_directory', '/sdcard/pgo_profile')
        jarlog = posixpath.join(outputdir, 'en-US.log')
        profdata = posixpath.join(outputdir, 'default_%p_random_%m.profraw')

        env = {}
        env["XPCOM_DEBUG_BREAK"] = "warn"
        env["MOZ_IN_AUTOMATION"] = "1"
        env["MOZ_JAR_LOG_FILE"] = jarlog
        env["LLVM_PROFILE_FILE"] = profdata

        adbdevice = ADBDevice(adb=adb, device='emulator-5554')
        adbdevice.mkdir(outputdir)

        try:
            # Run Fennec a first time to initialize its profile
            driver = Marionette(
                app='fennec',
                package_name=app,
                adb_path=adb,
                bin="target.apk",
                prefs=prefs,
                connect_to_running_emulator=True,
                startup_timeout=1000,
                env=env,
            )
            driver.start_session()

            # Now generate the profile and wait for it to complete
            for page in PAGES:
                driver.navigate("http://%s:%d/%s" % (IP, PORT, page))
                timeout = 2
                if 'Speedometer/index.html' in page:
                    # The Speedometer test actually runs many tests internally in
                    # javascript, so it needs extra time to run through them. The
                    # emulator doesn't get very far through the whole suite, but
                    # this extra time at least lets some of them process.
                    timeout = 360
                time.sleep(timeout)

            driver.set_context("chrome")
            driver.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
                    .createInstance(Components.interfaces.nsISupportsPRBool);
                Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null);
                return cancelQuit.data;
            """)
            driver.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit)
            """)

            # There is a delay between execute_script() returning and the profile data
            # actually getting written out, so poll the device until we get a profile.
            for i in range(50):
                if not adbdevice.process_exist(app):
                    break
                time.sleep(2)
            else:
                raise Exception("Android App (%s) never quit" % app)

            # Pull all the profraw files and en-US.log
            adbdevice.pull(outputdir, '/builds/worker/workspace/')
        except ADBTimeoutError:
            self.fatal('INFRA-ERROR: Failed with an ADBTimeoutError',
                       EXIT_STATUS_DICT[TBPL_RETRY])

        profraw_files = glob.glob('/builds/worker/workspace/*.profraw')
        if not profraw_files:
            self.fatal(
                'Could not find any profraw files in /builds/worker/workspace')
        merge_cmd = [
            os.path.join(os.environ['MOZ_FETCHES_DIR'],
                         'clang/bin/llvm-profdata'),
            'merge',
            '-o',
            '/builds/worker/workspace/merged.profdata',
        ] + profraw_files
        rc = subprocess.call(merge_cmd)
        if rc != 0:
            self.fatal(
                'INFRA-ERROR: Failed to merge profile data. Corrupt profile?',
                EXIT_STATUS_DICT[TBPL_RETRY])

        # tarfile doesn't support xz in this version of Python
        tar_cmd = [
            'tar',
            '-acvf',
            '/builds/worker/artifacts/profdata.tar.xz',
            '-C',
            '/builds/worker/workspace',
            'merged.profdata',
            'en-US.log',
        ]
        subprocess.check_call(tar_cmd)

        httpd.stop()
示例#5
0
    def run_tests(self):
        """
        Generate the PGO profile data
        """
        from mozhttpd import MozHttpd
        from mozprofile import Preferences
        from mozdevice import ADBDeviceFactory, ADBTimeoutError
        from six import string_types
        from marionette_driver.marionette import Marionette

        app = self.query_package_name()

        IP = "10.0.2.2"
        PORT = 8888

        PATH_MAPPINGS = {
            "/js-input/webkit/PerformanceTests":
            "third_party/webkit/PerformanceTests",
        }

        dirs = self.query_abs_dirs()
        topsrcdir = dirs["abs_src_dir"]
        adb = self.query_exe("adb")

        path_mappings = {
            k: os.path.join(topsrcdir, v)
            for k, v in PATH_MAPPINGS.items()
        }
        httpd = MozHttpd(
            port=PORT,
            docroot=os.path.join(topsrcdir, "build", "pgo"),
            path_mappings=path_mappings,
        )
        httpd.start(block=False)

        profile_data_dir = os.path.join(topsrcdir, "testing", "profiles")
        with open(os.path.join(profile_data_dir, "profiles.json"), "r") as fh:
            base_profiles = json.load(fh)["profileserver"]

        prefpaths = [
            os.path.join(profile_data_dir, profile, "user.js")
            for profile in base_profiles
        ]

        prefs = {}
        for path in prefpaths:
            prefs.update(Preferences.read_prefs(path))

        interpolation = {
            "server": "%s:%d" % httpd.httpd.server_address,
            "OOP": "false"
        }
        for k, v in prefs.items():
            if isinstance(v, string_types):
                v = v.format(**interpolation)
            prefs[k] = Preferences.cast(v)

        outputdir = self.config.get("output_directory", "/sdcard/pgo_profile")
        jarlog = posixpath.join(outputdir, "en-US.log")
        profdata = posixpath.join(outputdir, "default_%p_random_%m.profraw")

        env = {}
        env["XPCOM_DEBUG_BREAK"] = "warn"
        env["MOZ_IN_AUTOMATION"] = "1"
        env["MOZ_JAR_LOG_FILE"] = jarlog
        env["LLVM_PROFILE_FILE"] = profdata

        if self.query_minidump_stackwalk():
            os.environ["MINIDUMP_STACKWALK"] = self.minidump_stackwalk_path
        os.environ["MINIDUMP_SAVE_PATH"] = self.query_abs_dirs(
        )["abs_blob_upload_dir"]
        if not self.symbols_path:
            self.symbols_path = os.environ.get("MOZ_FETCHES_DIR")

        # Force test_root to be on the sdcard for android pgo
        # builds which fail for Android 4.3 when profiles are located
        # in /data/local/tmp/test_root with
        # E AndroidRuntime: FATAL EXCEPTION: Gecko
        # E AndroidRuntime: java.lang.IllegalArgumentException: \
        #    Profile directory must be writable if specified: /data/local/tmp/test_root/profile
        # This occurs when .can-write-sentinel is written to
        # the profile in
        # mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoProfile.java.
        # This is not a problem on later versions of Android. This
        # over-ride of test_root should be removed when Android 4.3 is no
        # longer supported.
        sdcard_test_root = "/sdcard/test_root"
        adbdevice = ADBDeviceFactory(adb=adb,
                                     device="emulator-5554",
                                     test_root=sdcard_test_root)
        if adbdevice.test_root != sdcard_test_root:
            # If the test_root was previously set and shared
            # the initializer will not have updated the shared
            # value. Force it to match the sdcard_test_root.
            adbdevice.test_root = sdcard_test_root
        adbdevice.mkdir(outputdir, parents=True)

        try:
            # Run Fennec a first time to initialize its profile
            driver = Marionette(
                app="fennec",
                package_name=app,
                adb_path=adb,
                bin="geckoview-androidTest.apk",
                prefs=prefs,
                connect_to_running_emulator=True,
                startup_timeout=1000,
                env=env,
                symbols_path=self.symbols_path,
            )
            driver.start_session()

            # Now generate the profile and wait for it to complete
            for page in PAGES:
                driver.navigate("http://%s:%d/%s" % (IP, PORT, page))
                timeout = 2
                if "Speedometer/index.html" in page:
                    # The Speedometer test actually runs many tests internally in
                    # javascript, so it needs extra time to run through them. The
                    # emulator doesn't get very far through the whole suite, but
                    # this extra time at least lets some of them process.
                    timeout = 360
                time.sleep(timeout)

            driver.set_context("chrome")
            driver.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
                    .createInstance(Components.interfaces.nsISupportsPRBool);
                Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null);
                return cancelQuit.data;
            """)
            driver.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit)
            """)

            # There is a delay between execute_script() returning and the profile data
            # actually getting written out, so poll the device until we get a profile.
            for i in range(50):
                if not adbdevice.process_exist(app):
                    break
                time.sleep(2)
            else:
                raise Exception("Android App (%s) never quit" % app)

            # Pull all the profraw files and en-US.log
            adbdevice.pull(outputdir, "/builds/worker/workspace/")
        except ADBTimeoutError:
            self.fatal(
                "INFRA-ERROR: Failed with an ADBTimeoutError",
                EXIT_STATUS_DICT[TBPL_RETRY],
            )

        profraw_files = glob.glob("/builds/worker/workspace/*.profraw")
        if not profraw_files:
            self.fatal(
                "Could not find any profraw files in /builds/worker/workspace")
        merge_cmd = [
            os.path.join(os.environ["MOZ_FETCHES_DIR"],
                         "clang/bin/llvm-profdata"),
            "merge",
            "-o",
            "/builds/worker/workspace/merged.profdata",
        ] + profraw_files
        rc = subprocess.call(merge_cmd)
        if rc != 0:
            self.fatal(
                "INFRA-ERROR: Failed to merge profile data. Corrupt profile?",
                EXIT_STATUS_DICT[TBPL_RETRY],
            )

        # tarfile doesn't support xz in this version of Python
        tar_cmd = [
            "tar",
            "-acvf",
            "/builds/worker/artifacts/profdata.tar.xz",
            "-C",
            "/builds/worker/workspace",
            "merged.profdata",
            "en-US.log",
        ]
        subprocess.check_call(tar_cmd)

        httpd.stop()
class current_frame():

    filename_screenshot = ""
    filename_htmldump = ""

    def main(self, LOGDIR):
        #
        # The first variable is the log directory.
        #
        ucount = 0
        self.marionette = Marionette(host='localhost', port=2828)
        self.marionette.start_session()
        self.marionette.set_search_timeout(1000)

        #
        # Now loop through all the iframes, gathering details about each one.
        #
        print ""
        print "Iframe for 'top level' () ..."
        self.filename_screenshot = LOGDIR + "top_level" + ".png"
        self.filename_htmldump = LOGDIR + "top_level" + ".html"
        self.marionette.switch_to_frame()
        self.record_frame()

        frames = self.marionette.find_elements("tag name", "iframe")
        for fnum in range(len(frames)):

            #
            # App name is usually in the "src" attribute, so it's worth a shot..
            #
            frame_src = frames[fnum].get_attribute("src")

            if frame_src != "":
                startpos = frame_src.index('/') + 2
                stoppos = frame_src.index('.')
                appname = frame_src[startpos:stoppos]
                filename = appname
            else:
                ucount = ucount + 1
                appname = "(unknown)"
                filename = "unknown_" + str(ucount)

            #
            # Because we call this script sometimes when we hit a Marionette issue,
            # these filenames may already exist (and we'd overwrite them!), so
            # add 'DEBUG_' to the start of the filename.
            #
            filename = "DEBUG_" + filename

            filename_details = LOGDIR + filename + "_iframe_details.txt"
            self.filename_screenshot = LOGDIR + filename + ".png"
            self.filename_htmldump = LOGDIR + filename + ".html"

            #
            # This iframe gives me problems sometimes, so I'm ignoring it for now.
            #
            if appname == "costcontrol":
                continue

            print ""
            print "Iframe for app \"" + appname + "\" ..."

            #
            # Record the iframe details (pretty verbose, but 'execute_script'
            # wasn't letting me use 'for' loops in js for some reason).
            #
            print "    |_ iframe details saved to : " + filename_details
            f = open(filename_details, 'w')
            f.write("Attributes for this iframe ...\n")
            num_attribs = self.marionette.execute_script("return document.getElementsByTagName('iframe')["
                                                         + str(fnum) + "].attributes.length;")
            for i in range(num_attribs):
                attrib_name = self.marionette.execute_script("return document.getElementsByTagName('iframe')["
                                                             + str(fnum) + "].attributes[" + str(i) + "].nodeName;")
                attrib_value = self.marionette.execute_script("return document.getElementsByTagName('iframe')["
                                                              + str(fnum) + "].attributes[" + str(i) + "].nodeValue;")

                f.write("    |_ " + attrib_name.ljust(20) + ": \"" + attrib_value + "\"\n")
            f.close()

            #
            # Switch to this frame.
            #
            self.marionette.switch_to_frame(fnum)

            if appname == "keyboard":
                #
                # Take the html dump and save it to the file.
                #
                print "    |_ html dump saved to      : " + self.filename_htmldump
                f = open(self.filename_htmldump, 'w')
                f.write(self.marionette.page_source.encode('utf8', 'ignore'))
                f.close()
            else:
                self.record_frame()

            self.marionette.switch_to_frame()

    def record_frame(self):
        #
        # Take the screenshot and save it to the file.
        #
        print "    |_ screenshot saved to     : " + self.filename_screenshot
        screenshot = self.marionette.screenshot()
        with open(self.filename_screenshot, 'w') as f:
            f.write(base64.decodestring(screenshot))
        f.close()

        #
        # Take the html dump and save it to the file.
        #
        print "    |_ html dump saved to      : " + self.filename_htmldump
        f = open(self.filename_htmldump, 'w')
        f.write(self.marionette.page_source.encode('utf8', 'ignore'))
        f.close()
class MuletReftest(RefTest):
    build_type = "mulet"
    marionette = None

    def __init__(self, marionette_args):
        RefTest.__init__(self)
        self.last_test = os.path.basename(__file__)
        self.marionette_args = marionette_args
        self.profile = None
        self.runner = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.timeout = None

    def run_marionette_script(self):
        self.marionette = Marionette(**self.marionette_args)
        assert(self.marionette.wait_for_port())
        self.marionette.start_session()
        if self.build_type == "mulet":
            self._wait_for_homescreen(timeout=300)
            self._unlockScreen()
        self.marionette.set_context(self.marionette.CONTEXT_CHROME)

        if os.path.isfile(self.test_script):
            f = open(self.test_script, 'r')
            self.test_script = f.read()
            f.close()
        self.marionette.execute_script(self.test_script)

    def run_tests(self, tests, options):
        manifests = self.resolver.resolveManifests(options, tests)

        self.profile = self.create_profile(options, manifests,
                                           profile_to_clone=options.profile)
        env = self.buildBrowserEnv(options, self.profile.profile)

        self._populate_logger(options)
        outputHandler = OutputHandler(self.log, options.utilityPath, symbolsPath=options.symbolsPath)

        kp_kwargs = { 'processOutputLine': [outputHandler],
                      'onTimeout': [self._on_timeout],
                      'kill_on_timeout': False }

        if not options.debugger:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            self.timeout = options.timeout + 30.0

        self.log.info("%s | Running tests: start." % os.path.basename(__file__))
        cmd, args = self.build_command_line(options.app,
                            ignore_window_size=options.ignoreWindowSize,
                            browser_arg=options.browser_arg)
        self.runner = FirefoxRunner(profile=self.profile,
                                    binary=cmd,
                                    cmdargs=args,
                                    env=env,
                                    process_class=ProcessHandler,
                                    process_args=kp_kwargs,
                                    symbols_path=options.symbolsPath)

        status = 0
        try:
            self.runner.start(outputTimeout=self.timeout)
            self.log.info("%s | Application pid: %d" % (
                     os.path.basename(__file__),
                     self.runner.process_handler.pid))

            # kick starts the reftest harness
            self.run_marionette_script()
            status = self.runner.wait()
        finally:
            self.runner.check_for_crashes(test_name=self.last_test)
            self.runner.cleanup()

        if status > 0:
            self.log.testFail("%s | application terminated with exit code %s" % (
                         self.last_test, status))
        elif status < 0:
            self.log.info("%s | application killed with signal %s" % (
                         self.last_test, -status))

        self.log.info("%s | Running tests: end." % os.path.basename(__file__))
        return status

    def create_profile(self, options, manifests, profile_to_clone=None):
        profile = RefTest.createReftestProfile(self, options, manifests,
                                               profile_to_clone=profile_to_clone)

        prefs = {}
        # Turn off the locale picker screen
        prefs["browser.firstrun.show.localepicker"] = False
        if not self.build_type == "mulet":
            # FIXME: With Mulet we can't set this values since Gaia won't launch
            prefs["b2g.system_startup_url"] = \
                    "app://test-container.gaiamobile.org/index.html"
            prefs["b2g.system_manifest_url"] = \
                    "app://test-container.gaiamobile.org/manifest.webapp"
        # Make sure we disable system updates
        prefs["app.update.enabled"] = False
        prefs["app.update.url"] = ""
        # Disable webapp updates
        prefs["webapps.update.enabled"] = False
        # Disable tiles also
        prefs["browser.newtabpage.directory.source"] = ""
        prefs["browser.newtabpage.directory.ping"] = ""
        prefs["dom.ipc.tabs.disabled"] = False
        prefs["dom.mozBrowserFramesEnabled"] = True
        prefs["font.size.inflation.emPerLine"] = 0
        prefs["font.size.inflation.minTwips"] = 0
        prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org"
        prefs["reftest.browser.iframe.enabled"] = False
        prefs["reftest.remote"] = False

        # Set the extra prefs.
        profile.set_preferences(prefs)
        return profile

    def build_command_line(self, app, ignore_window_size=False,
                           browser_arg=None):
        cmd = os.path.abspath(app)
        args = ['-marionette']

        if browser_arg:
            args += [browser_arg]

        if not ignore_window_size:
            args.extend(['--screen', '800x1000'])

        if self.build_type == "mulet":
            args += ['-chrome', 'chrome://b2g/content/shell.html']
        return cmd, args

    def _on_timeout(self):
        msg = "%s | application timed out after %s seconds with no output"
        self.log.testFail(msg % (self.last_test, self.timeout))
        self.log.error("Force-terminating active process(es).");

        # kill process to get a stack
        self.runner.stop(sig=signal.SIGABRT)

    def _unlockScreen(self):
        self.marionette.set_context(self.marionette.CONTEXT_CONTENT)
        self.marionette.import_script(os.path.abspath(
            os.path.join(__file__, os.path.pardir, "gaia_lock_screen.js")))
        self.marionette.switch_to_frame()
        self.marionette.execute_async_script('GaiaLockScreen.unlock()')

    def _wait_for_homescreen(self, timeout):
        self.log.info("Waiting for home screen to load")
        Wait(self.marionette, timeout).until(expected.element_present(
            By.CSS_SELECTOR, '#homescreen[loading-state=false]'))
示例#8
0
文件: gcli.py 项目: kuoe0/gaia-dev
class GCli(object):

    def __init__(self):
        self.commands = {
            'connectwifi': {
                'function': self.connect_to_wifi,
                'args': [
                    {'name': 'ssid',
                     'help': 'SSID of the network to connect to'},
                    {'name': '--security',
                     'choices': ['WPA-PSK', 'WEP'],
                     'help': 'Security model of the network'},
                    {'name': '--password',
                     'help': 'Password to access the network'}],
                'help': 'Connect to a WiFi network'},
            'disablewifi': {
                'function': self.disable_wifi,
                'help': 'Disable WiFi'},
            'enablewifi': {
                'function': self.enable_wifi,
                'help': 'Enable WiFi'},
            'forgetallwifi': {
                'function': self.forget_all_wifi_networks,
                'help': 'Forget all WiFi networks'},
            'getknownwifi': {
                'function': self.known_wifi_networks,
                'help': 'Show known WiFi networks'},
            'getsetting': {
                'function': self.get_setting,
                'args': [{
                    'name': 'name',
                    'help': 'Name of the setting to retrieve'}],
                'help': 'Show the current value of a setting'},
            'holdhome': {
                'function': self.hold_home,
                'help': 'Simulate holding the home button'},
            'holdsleep': {
                'function': self.hold_sleep,
                'help': 'Simulate holding the sleep button'},
            'home': {
                'function': self.home,
                'help': 'Simulate pressing the home button'},
            'killapps': {
                'function': self.kill_all_apps,
                'help': 'Kill all running apps'},
            'launchapp': {
                'function': self.launch_app,
                'args': [
                    {'name': 'name',
                     'nargs': argparse.REMAINDER,
                     'help': 'Name of app to launch'}],
                'help': 'Launch an application'},
            'listallapps': {
                'function': self.list_all_apps,
                'help': 'List all apps'},
            'listrunningapps': {
                'function': self.list_running_apps,
                'help': 'List the running apps'},
            'lock': {
                'function': self.lock,
                'help': 'Lock screen'},
            'screenshot': {
                'function': self.screenshot,
                'help': 'Take a screenshot'},
            'sendsms': {
                'function': self.send_sms,
                'args': [
                    {'name': 'number',
                     'help': 'Phone number of recipient'},
                    {'name': 'message',
                     'help': 'Message content'}],
                'help': 'Send an SMS'},
            'setsetting': {
                'function': self.set_setting,
                'args': [
                    {'name': 'name',
                     'help': 'Name of setting to change'},
                    {'name': 'value',
                     'help': 'New value for setting'}],
                'help': 'Change the value of a setting'},
            'sleep': {
                'function': self.sleep,
                'help': 'Enter sleep mode'},
            'unlock': {
                'function': self.unlock,
                'help': 'Unlock screen'},
            'volume': {
                'function': self.volume,
                'args': [
                    {'name': 'direction',
                     'choices': ['down', 'up'],
                     'help': 'Direction to change the volume'}],
                'help': 'Change the volume'},
            'wake': {
                'function': self.wake,
                'help': 'Wake from sleep mode'}}

        self.parser = argparse.ArgumentParser()
        self.add_options(self.parser)
        self.add_commands(self.parser)

    def run(self, args=sys.argv[1:]):
        args = self.parser.parse_args()

        host, port = args.address.split(':')
        self.marionette = Marionette(host=host, port=int(port))
        self.marionette.start_session()

        self.apps = gaiatest.GaiaApps(self.marionette)
        self.data_layer = gaiatest.GaiaData(self.marionette)
        self.device = gaiatest.GaiaDevice(self.marionette)

        ret = args.func(args)
        if ret is None:
            ret = 0

        self.marionette.delete_session()

        sys.exit(ret)

    def add_options(self, parser):
        parser.add_argument(
            '--address',
            default='localhost:2828',
            help='Address (host:port) of running Gecko instance to connect to '
                 '(default: %(default)s)')

    def add_commands(self, parser):
        subparsers = parser.add_subparsers(
            title='Commands', metavar='<command>')
        for (name, props) in sorted(self.commands.iteritems()):
            subparser = subparsers.add_parser(name, help=props['help'])
            if props.get('args'):
                for arg in props['args']:
                    kwargs = {k: v for k, v in arg.items() if k is not 'name'}
                    subparser.add_argument(arg['name'], **kwargs)
            subparser.set_defaults(func=props['function'])

    def connect_to_wifi(self, args):
        network = {
            'ssid': args.ssid,
            'keyManagement': args.security or 'NONE'}
        if args.security == 'WEP':
            network['wep'] = args.password
        elif args.security == 'WPA-PSK':
            network['psk'] = args.password
        self.data_layer.connect_to_wifi(network)

    def disable_wifi(self, args):
        self.data_layer.disable_wifi()

    def enable_wifi(self, args):
        self.data_layer.enable_wifi()

    def forget_all_wifi_networks(self, args):
        self.data_layer.forget_all_networks()

    def get_setting(self, args):
        print '%s: %s' % (
            args.name,
            self.data_layer.get_setting(args.name))

    def home(self, args):
        self.device.touch_home_button()

    def hold_home(self, args):
        self.device.hold_home_button()

    def hold_sleep(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('holdsleep'));")

    def kill_all_apps(self, args):
        self.apps.kill_all()

    def known_wifi_networks(self, args):
        networks = [n for n in self.data_layer.known_networks if 'ssid' in n]
        if len(networks) > 0:
            for i, network in enumerate(networks):
                print '%s: %s' % (i + 1, network['ssid'])
        else:
            print 'No known networks.'

    def launch_app(self, args):
        for name in args.name:
            self.apps.launch(name)

    def list_all_apps(self, args):
        for i, app in enumerate(sorted(self.apps.installed_apps,
                                       key=lambda a: a.name.lower())):
            print '%d: %s' % (i + 1, app.name)

    def list_running_apps(self, args):
        for i, app in enumerate(sorted(self.apps.running_apps,
                                       key=lambda a: a.name.lower())):
            print '%d: %s' % (i + 1, app.name)

    def lock(self, args):
        self.device.lock()

    def screenshot(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('volumedown+sleep'));")

    def send_sms(self, args):
        self.data_layer.send_sms(args.number, args.message)

    def set_setting(self, args):
        self.data_layer.set_setting(args.name, args.value)

    def sleep(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('sleep'));")

    def unlock(self, args):
        self.device.unlock()

    def volume(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('volume%s'));" %
            args.direction)

    def wake(self, args):
        self.marionette.execute_script(
            "window.wrappedJSObject.dispatchEvent(new Event('wake'));")
示例#9
0
def run_firefox(args):
    logger = logging.getLogger('sisyphus')
    logger.setLevel(logging.DEBUG)
    streamhandler = logging.StreamHandler(stream=sys.stdout)
    streamformatter = logging.Formatter(
        '%(asctime)s %(name)15s %(levelname)-8s %(message)s')
    streamhandler.setFormatter(streamformatter)
    logger.addHandler(streamhandler)

    # On Windows, make sure we point to the same temp directory as cygwin.
    if platform.system() == 'Windows':
        tempfile.tempdir = 'C:\\cygwin\\tmp'
    # Clean up tmpaddons
    tmpaddons = glob.glob(os.path.join(tempfile.gettempdir(), 'tmpaddon*'))
    for tmpaddon in tmpaddons:
        os.unlink(tmpaddon)

    # Work around Windows issues with shell metacharacters in url.
    if not args.url:
        if "URL" in os.environ:
            args.url = os.environ["URL"]
        else:
            logger.error("run_firefox: url is required")
            return

    # Load preferences of the form name=value from the
    # command line arguments.
    def eval_value(value):
        """Convert preference string value"""
        if value == 'true':
            value = True
        elif value == 'false':
            value = False
        else:
            try:
                value = eval(value)
            except NameError:
                # Leave string value alone.
                pass
        return value

    mozprofile_preferences = mozprofile.prefs.Preferences()

    preferences = {}
    set_preference_args = []
    for set_preference_arg in args.set_preferences:
        (name, value) = set_preference_arg.split('=', 1)
        set_preference_args.append((name, eval_value(value)))

    preferences.update(dict(set_preference_args))

    # Load preferences of from json files.
    for preference_json_arg in args.preference_jsons:
        preferences.update(
            dict(mozprofile_preferences.read_json(preference_json_arg)))

    # Load preferences from Firefox prefs.js/user.js files.
    for preference_file_arg in args.preference_files:
        preferences.update(
            dict(mozprofile_preferences.read_prefs(preference_file_arg)))

    logger.info("preferences: %s",
                json.dumps(preferences, indent=2, sort_keys=True))

    profile = mozprofile.profile.FirefoxProfile(profile=args.profile,
                                                preferences=preferences)
    client = Marionette(host='localhost',
                        port=2828,
                        bin=args.binary,
                        profile=profile,
                        gecko_log=args.gecko_log,
                        symbols_path=args.symbols_path)

    client.start_session()
    if args.restart:
        client.restart(clean=False, in_app=True)
    client.maximize_window()

    references = {'time_out_alarm_fired': False}

    if hasattr(signal, 'SIGALRM'):
        # Windows doesn't support SIGALRM. marionette
        # doesn't support cygwin paths...
        def timeout_handler(signum, frame):
            logger.warning("navigate: %s timed out" % args.url)
            references['time_out_alarm_fired'] = True
            client.quit()

        default_alarm_handler = signal.getsignal(signal.SIGALRM)

        signal.signal(signal.SIGALRM, timeout_handler)
        signal.alarm(args.page_load_timeout + 2 * args.script_timeout)

    try:
        client.timeout.page_load = args.page_load_timeout
        client.timeout.script = args.script_timeout
        # Register the dialog closer for the browser. If the download
        # dialog appears, it will be closed and the browser window
        # will be closed. This forces marionette to return from
        # navigate and works around Bug 1366035. This version does
        # not dismiss normal Alerts which can be handled by Marionette's Alert.
        dialog_closer_script = """
var gDialogCloser;
var gDialogCloserObserver;
var gDialogCloserSubjects = [];

registerDialogCloser = function () {
  gDialogCloser = Components.classes['@mozilla.org/embedcomp/window-watcher;1'].getService(Components.interfaces.nsIWindowWatcher);
  gDialogCloserObserver = {observe: dialogCloser_observe};
  gDialogCloser.registerNotification(gDialogCloserObserver);
}

unregisterDialogCloser = function () {
  if (!gDialogCloserObserver || !gDialogCloser)
  {
    return;
  }

  gDialogCloser.unregisterNotification(gDialogCloserObserver);
  gDialogCloserObserver = null;
  gDialogCloser = null;
}

dialogCloser_observe = function (subject, topic, data) {
  if (subject instanceof ChromeWindow && topic == 'domwindowopened' )
  {
    gDialogCloserSubjects.push(subject);
    subject.setTimeout(closeDialog, 5000)
  }
}

closeDialog = function () {
  var subject;
  while ( (subject = gDialogCloserSubjects.pop()) != null)
  {
      if (subject.document instanceof XULDocument) {
          var uri = subject.document.documentURI;
          //if (uri.startsWith('chrome://') && uri.endsWith('ialog.xul')) {
          //    subject.close();
          //} else
          if (uri == 'chrome://mozapps/content/downloads/unknownContentType.xul') {
              dump('Sisyphus Runner: Closing Window due to download dialog\\n');
              subject.close();
              window.close();
          }
      }
  }
}

registerDialogCloser();
"""
        client.set_context(client.CONTEXT_CHROME)
        client.execute_script(dialog_closer_script,
                              new_sandbox=False,
                              script_timeout=client.timeout.script)
        client.set_context(client.CONTEXT_CONTENT)
        try:
            logger.info('New Page: %s' % args.url)
            client.navigate(args.url)
            client.maximize_window()
        except Exception, e:
            logger.warning('navigate: %s', e)

        # Do not call client.check_for_crash() as that will invoke
        # mozcrash which will delete the dump files. Handle the dumps
        # in the caller.
        client.set_context(client.CONTEXT_CONTENT)
        for content_script_url in args.content_scripts:
            content_script = get_remote_text(content_script_url)
            if content_script:
                try:
                    logger.info('<contentscript>\n%s\n</contentscript>',
                                content_script)
                    result = client.execute_script(
                        content_script,
                        script_args=[],
                        script_timeout=client.timeout.script)
                    logger.info('content script result: %s', result)
                except errors.ScriptTimeoutException, e:
                    logger.warning('content script: %s', e)
                except Exception, e:
                    logger.error('content script: %s', e)
示例#10
0
class Firefox(DesktopBrowser):
    """Firefox"""
    def __init__(self, path, options, job):
        DesktopBrowser.__init__(self, path, options, job)
        self.job = job
        self.task = None
        self.options = options
        self.path = path
        self.event_name = None
        self.moz_log = None
        self.marionette = None
        self.addons = None
        self.extension_id = None
        self.nav_error = None
        self.page_loaded = None
        self.recording = False
        self.connected = False
        self.start_offset = None
        self.browser_version = None
        self.log_pos = {}
        self.page = {}
        self.requests = {}
        self.last_activity = monotonic.monotonic()
        self.script_dir = os.path.join(
            os.path.abspath(os.path.dirname(__file__)), 'js')
        self.start_page = 'http://127.0.0.1:8888/orange.html'

    def prepare(self, job, task):
        """Prepare the profile/OS for the browser"""
        self.moz_log = os.path.join(task['dir'], 'moz.log')
        self.log_pos = {}
        self.page = {}
        self.requests = {}
        os.environ["MOZ_LOG_FILE"] = self.moz_log
        os.environ["MOZ_LOG"] = 'timestamp,sync,nsHttp:5,nsSocketTransport:5'\
                                'nsHostResolver:5,pipnss:5'
        DesktopBrowser.prepare(self, job, task)
        profile_template = os.path.join(
            os.path.abspath(os.path.dirname(__file__)), 'support', 'Firefox',
            'profile')
        if not task['cached'] and os.path.isdir(profile_template):
            try:
                if os.path.isdir(task['profile']):
                    shutil.rmtree(task['profile'])
                shutil.copytree(profile_template, task['profile'])
            except Exception:
                pass
        # delete any unsent crash reports
        crash_dir = None
        if platform.system() == 'Windows':
            if 'APPDATA' in os.environ:
                crash_dir = os.path.join(os.environ['APPDATA'], 'Mozilla',
                                         'Firefox', 'Crash Reports')
        else:
            crash_dir = os.path.join(os.path.expanduser('~'), '.mozilla',
                                     'firefox', 'Crash Reports')
        if crash_dir and os.path.isdir(crash_dir):
            logging.debug("Clearing crash reports in %s", crash_dir)
            try:
                shutil.rmtree(crash_dir)
            except Exception:
                pass
        # Prepare the config for the extension to query
        if self.job['message_server'] is not None:
            config = None
            names = [
                'block', 'block_domains', 'block_domains_except', 'headers',
                'cookies'
            ]
            for name in names:
                if name in task and task[name]:
                    if config is None:
                        config = {}
                    config[name] = task[name]
            self.job['message_server'].config = config

    def launch(self, job, task):
        """Launch the browser"""
        if self.job['message_server'] is not None:
            self.job['message_server'].flush_messages()
        self.connected = False
        from marionette_driver.marionette import Marionette
        from marionette_driver.addons import Addons
        args = [
            '-profile', '"{0}"'.format(task['profile']), '-no-remote',
            '-marionette', 'about:blank'
        ]
        if self.path.find(' ') > -1:
            command_line = '"{0}"'.format(self.path)
        else:
            command_line = self.path
        command_line += ' ' + ' '.join(args)
        DesktopBrowser.launch_browser(self, command_line)
        try:
            self.marionette = Marionette('localhost', port=2828)
            self.marionette.start_session(timeout=self.task['time_limit'])
            self.configure_prefs()
            logging.debug('Installing extension')
            self.addons = Addons(self.marionette)
            extension_path = os.path.join(
                os.path.abspath(os.path.dirname(__file__)), 'support',
                'Firefox', 'extension')
            self.extension_id = self.addons.install(extension_path, temp=True)
            logging.debug('Resizing browser to %dx%d', task['width'],
                          task['height'])
            self.marionette.set_window_position(x=0, y=0)
            self.marionette.set_window_size(height=task['height'],
                                            width=task['width'])
            if 'browserVersion' in self.marionette.session_capabilities:
                self.browser_version = self.marionette.session_capabilities[
                    'browserVersion']
            self.marionette.navigate(self.start_page)
            time.sleep(0.5)
            self.wait_for_extension()
            if self.connected:
                # Override the UA String if necessary
                ua_string = self.execute_js('navigator.userAgent;')
                modified = False
                if 'uastring' in self.job:
                    ua_string = self.job['uastring']
                    modified = True
                if ua_string is not None and 'AppendUA' in task:
                    ua_string += ' ' + task['AppendUA']
                    modified = True
                if modified:
                    logging.debug(ua_string)
                    self.marionette.set_pref('general.useragent.override',
                                             ua_string)
                # Figure out the native viewport size
                size = self.execute_js(
                    "[window.innerWidth, window.innerHeight]")
                logging.debug(size)
                if size is not None and len(size) == 2:
                    task['actual_viewport'] = {
                        "width": size[0],
                        "height": size[1]
                    }
                    if 'adjust_viewport' in job and job['adjust_viewport']:
                        delta_x = max(task['width'] - size[0], 0)
                        delta_y = max(task['height'] - size[1], 0)
                        if delta_x or delta_y:
                            width = task['width'] + delta_x
                            height = task['height'] + delta_y
                            logging.debug('Resizing browser to %dx%d', width,
                                          height)
                            self.marionette.set_window_position(x=0, y=0)
                            self.marionette.set_window_size(height=height,
                                                            width=width)
                # Wait for the browser startup to finish
                DesktopBrowser.wait_for_idle(self)
        except Exception as err:
            task['error'] = 'Error starting Firefox: {0}'.format(err.__str__())

    def get_pref_value(self, value):
        """Convert a json pref value to Python"""
        str_match = re.match(r'^"(.*)"$', value)
        if value == 'true':
            value = True
        elif value == 'false':
            value = False
        elif re.match(r'^[\d]+$', value):
            value = int(value)
        elif str_match:
            value = str_match.group(1)
        else:
            value = None
        return value

    def configure_prefs(self):
        """Load the prefs file and configure them through marionette"""
        prefs = {}
        prefs_file = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                  'support', 'Firefox', 'profile', 'prefs.js')
        with open(prefs_file) as f_in:
            for line in f_in:
                matches = re.search(
                    r'user_pref\("([^"]+)",[\s]*([^\)]*)[\s]*\);', line)
                if matches:
                    key = matches.group(1).strip()
                    value = self.get_pref_value(matches.group(2).strip())
                    if value is not None:
                        prefs[key] = value
        if prefs:
            try:
                self.marionette.set_prefs(prefs, True)
            except Exception:
                pass

    def stop(self, job, task):
        """Kill the browser"""
        if self.extension_id is not None and self.addons is not None:
            try:
                self.addons.uninstall(self.extension_id)
            except Exception:
                pass
            self.extension_id = None
            self.addons = None
        if self.marionette is not None:
            try:
                self.marionette.close()
            except Exception:
                pass
            self.marionette = None
        DesktopBrowser.stop(self, job, task)
        # Make SURE the firefox processes are gone
        if platform.system() == "Linux":
            subprocess.call(['killall', '-9', 'firefox'])
            subprocess.call(['killall', '-9', 'firefox-trunk'])
        os.environ["MOZ_LOG_FILE"] = ''
        os.environ["MOZ_LOG"] = ''
        # delete the raw log files
        if self.moz_log is not None:
            files = sorted(glob.glob(self.moz_log + '*'))
            for path in files:
                try:
                    os.remove(path)
                except Exception:
                    pass

    def run_lighthouse_test(self, task):
        """Stub for lighthouse test"""
        pass

    def run_task(self, task):
        """Run an individual test"""
        if self.marionette is not None and self.connected:
            self.task = task
            logging.debug("Running test")
            end_time = monotonic.monotonic() + task['test_time_limit']
            task['current_step'] = 1
            recording = False
            while len(task['script']) and task['error'] is None and \
                    monotonic.monotonic() < end_time:
                self.prepare_task(task)
                command = task['script'].pop(0)
                if not recording and command['record']:
                    recording = True
                    self.on_start_recording(task)
                try:
                    self.process_command(command)
                except Exception:
                    logging.exception("Exception running task")
                if command['record']:
                    self.wait_for_page_load()
                    if not task['combine_steps'] or not len(task['script']):
                        self.on_stop_recording(task)
                        recording = False
                        self.on_start_processing(task)
                        self.wait_for_processing(task)
                        self.step_complete(task)
                        if task['log_data']:
                            # Move on to the next step
                            task['current_step'] += 1
                            self.event_name = None
                    task['navigated'] = True
            # Always navigate to about:blank after finishing in case the tab is
            # remembered across sessions
            try:
                self.marionette.navigate('about:blank')
            except Exception:
                logging.debug(
                    'Marionette exception navigating to about:blank after the test'
                )
            self.task = None

    def wait_for_extension(self):
        """Wait for the extension to send the started message"""
        if self.job['message_server'] is not None:
            end_time = monotonic.monotonic() + 30
            while monotonic.monotonic() < end_time:
                try:
                    self.job['message_server'].get_message(1)
                    logging.debug('Extension started')
                    self.connected = True
                    break
                except Exception:
                    pass

    def wait_for_page_load(self):
        """Wait for the onload event from the extension"""
        if self.job['message_server'] is not None and self.connected:
            start_time = monotonic.monotonic()
            end_time = start_time + self.task['time_limit']
            done = False
            while not done:
                try:
                    self.process_message(
                        self.job['message_server'].get_message(1))
                except Exception:
                    pass
                now = monotonic.monotonic()
                elapsed_test = now - start_time
                if self.nav_error is not None:
                    done = True
                    if self.page_loaded is None:
                        self.task['error'] = self.nav_error
                elif now >= end_time:
                    done = True
                    # only consider it an error if we didn't get a page load event
                    if self.page_loaded is None:
                        self.task['error'] = "Page Load Timeout"
                elif 'time' not in self.job or elapsed_test > self.job['time']:
                    elapsed_activity = now - self.last_activity
                    elapsed_page_load = now - self.page_loaded if self.page_loaded else 0
                    if elapsed_page_load >= 1 and elapsed_activity >= self.task[
                            'activity_time']:
                        done = True
                    elif self.task['error'] is not None:
                        done = True

    def execute_js(self, script):
        """Run javascipt"""
        ret = None
        if self.marionette is not None:
            try:
                ret = self.marionette.execute_script('return ' + script,
                                                     script_timeout=30)
            except Exception:
                pass
        return ret

    def run_js_file(self, file_name):
        """Execute one of our js scripts"""
        ret = None
        script = None
        script_file_path = os.path.join(self.script_dir, file_name)
        if os.path.isfile(script_file_path):
            with open(script_file_path, 'rb') as script_file:
                script = script_file.read()
        if script is not None:
            try:
                ret = self.marionette.execute_script('return ' + script,
                                                     script_timeout=30)
            except Exception:
                pass
            if ret is not None:
                logging.debug(ret)
        return ret

    def collect_browser_metrics(self, task):
        """Collect all of the in-page browser metrics that we need"""
        logging.debug("Collecting user timing metrics")
        user_timing = self.run_js_file('user_timing.js')
        if user_timing is not None:
            path = os.path.join(task['dir'],
                                task['prefix'] + '_timed_events.json.gz')
            with gzip.open(path, 'wb', 7) as outfile:
                outfile.write(json.dumps(user_timing))
        logging.debug("Collecting page-level metrics")
        page_data = self.run_js_file('page_data.js')
        if page_data is not None:
            task['page_data'].update(page_data)
        if 'customMetrics' in self.job:
            custom_metrics = {}
            for name in self.job['customMetrics']:
                logging.debug("Collecting custom metric %s", name)
                script = 'var wptCustomMetric = function() {' +\
                         self.job['customMetrics'][name] +\
                         '};try{return wptCustomMetric();}catch(e){};'
                try:
                    custom_metrics[name] = self.marionette.execute_script(
                        script, script_timeout=30)
                    if custom_metrics[name] is not None:
                        logging.debug(custom_metrics[name])
                except Exception:
                    pass
            path = os.path.join(task['dir'],
                                task['prefix'] + '_metrics.json.gz')
            with gzip.open(path, 'wb', 7) as outfile:
                outfile.write(json.dumps(custom_metrics))

    def process_message(self, message):
        """Process a message from the extension"""
        logging.debug(message)
        if self.recording:
            self.last_activity = monotonic.monotonic()
            try:
                # Make all of the timestamps relative to the test start to match the log events
                if 'timeStamp' in message['body']:
                    timestamp = message['body']['timeStamp']
                    seconds = int(timestamp / 1000)
                    milliseconds = timestamp - (seconds * 1000)
                    event_time = datetime.utcfromtimestamp(seconds)
                    event_time += timedelta(milliseconds=milliseconds)
                    elapsed = event_time - self.task['start_time']
                    message['body']['timeStamp'] = elapsed.total_seconds()
                cat, msg = message['path'].split('.', 1)
                if cat == 'webNavigation':
                    self.process_web_navigation(msg, message['body'])
                elif cat == 'webRequest':
                    self.process_web_request(msg, message['body'])
            except Exception:
                pass

    def process_web_navigation(self, message, evt):
        """Handle webNavigation.*"""
        if evt is not None:
            if message == 'onBeforeNavigate':
                if 'frameId' in evt and evt['frameId'] == 0:
                    self.page_loaded = None
                    logging.debug("Starting navigation")
                    if 'timeStamp' in evt and 'start' not in self.page:
                        self.page['start'] = evt['timeStamp']
            elif message == 'onCommitted':
                if 'timeStamp' in evt and 'frameId' in evt and evt['frameId'] == 0 \
                        and 'committed' not in self.page:
                    self.page['committed'] = evt['timeStamp']
                if 'injectScript' in self.job and self.marionette is not None:
                    logging.debug("Injecting script: \n%s",
                                  self.job['injectScript'])
                    try:
                        self.marionette.execute_script(
                            self.job['injectScript'], script_timeout=30)
                    except Exception:
                        pass
            elif message == 'onDOMContentLoaded':
                if 'timeStamp' in evt and 'frameId' in evt and evt[
                        'frameId'] == 0:
                    self.page['DOMContentLoaded'] = evt['timeStamp']
            elif message == 'onCompleted':
                if 'frameId' in evt and evt['frameId'] == 0:
                    self.page_loaded = monotonic.monotonic()
                    logging.debug("Page loaded")
                    if 'timeStamp' in evt:
                        self.page['loaded'] = evt['timeStamp']
            elif message == 'onErrorOccurred':
                if 'frameId' in evt and evt['frameId'] == 0:
                    self.page_loaded = monotonic.monotonic()
                    logging.debug("Page load failed")
                    if 'error' in evt:
                        self.nav_error = evt['error']
                    else:
                        self.nav_error = 'Navigation failed'

    def process_web_request(self, message, evt):
        """Handle webNavigation.*"""
        if evt is not None and 'requestId' in evt and 'timeStamp' in evt:
            if evt['requestId'] not in self.requests:
                self.requests[evt['requestId']] = {
                    'id': evt['requestId'],
                    'from_net': True
                }
            request = self.requests[evt['requestId']]
            if 'url' in evt and 'url' not in request:
                request['url'] = evt['url']
            if 'method' in evt and 'method' not in request:
                request['method'] = evt['method']
            if 'type' in evt and 'type' not in request:
                request['type'] = evt['type']
            if 'ip' in evt and 'ip' not in request:
                request['ip'] = evt['ip']
            if 'fromCache' in evt and evt['fromCache']:
                request['from_net'] = False
            if 'statusLine' in evt:
                request['status_line'] = evt['statusLine']
            if 'statusCode' in evt:
                request['status'] = evt['statusCode']
            if 'requestHeaders' in evt and 'request_headers' not in request:
                request['request_headers'] = list(evt['requestHeaders'])
            if 'responseHeaders' in evt and 'response_headers' not in request:
                request['response_headers'] = list(evt['responseHeaders'])

            if message == 'onBeforeRequest':
                request['created'] = evt['timeStamp']
            elif message == 'onSendHeaders':
                request['start'] = evt['timeStamp']
            elif message == 'onBeforeRedirect':
                if 'first_byte' not in request:
                    request['first_byte'] = evt['timeStamp']
                if 'end' not in request or evt['timeStamp'] > request['end']:
                    request['end'] = evt['timeStamp']
            elif message == 'onHeadersReceived':
                if 'first_byte' not in request:
                    request['first_byte'] = evt['timeStamp']
                if 'end' not in request or evt['timeStamp'] > request['end']:
                    request['end'] = evt['timeStamp']
            elif message == 'onResponseStarted':
                if 'first_byte' not in request:
                    request['first_byte'] = evt['timeStamp']
                if 'end' not in request or evt['timeStamp'] > request['end']:
                    request['end'] = evt['timeStamp']
            elif message == 'onCompleted':
                if 'first_byte' not in request:
                    request['first_byte'] = evt['timeStamp']
                if 'end' not in request or evt['timeStamp'] > request['end']:
                    request['end'] = evt['timeStamp']
            elif message == 'onErrorOccurred':
                if 'end' not in request or evt['timeStamp'] > request['end']:
                    request['end'] = evt['timeStamp']
                if 'error' in evt:
                    request['error'] = evt['error']
                if 'status' not in request:
                    request['status'] = 12999

    def prepare_task(self, task):
        """Format the file prefixes for multi-step testing"""
        if task['current_step'] == 1:
            task['prefix'] = task['task_prefix']
            task['video_subdirectory'] = task['task_video_prefix']
        else:
            task['prefix'] = '{0}_{1:d}'.format(task['task_prefix'],
                                                task['current_step'])
            task['video_subdirectory'] = '{0}_{1:d}'.format(
                task['task_video_prefix'], task['current_step'])
        if task['video_subdirectory'] not in task['video_directories']:
            task['video_directories'].append(task['video_subdirectory'])
        if self.event_name is not None:
            task['step_name'] = self.event_name
        else:
            task['step_name'] = 'Step_{0:d}'.format(task['current_step'])

    def on_start_recording(self, task):
        """Notification that we are about to start an operation that needs to be recorded"""
        # Clear the state
        self.page = {}
        self.requests = {}
        task['page_data'] = {'date': time.time()}
        task['page_result'] = None
        task['run_start_time'] = monotonic.monotonic()
        if self.browser_version is not None and 'browserVersion' not in task[
                'page_data']:
            task['page_data']['browserVersion'] = self.browser_version
            task['page_data']['browser_version'] = self.browser_version
        # Mark the start point in the various log files
        self.log_pos = {}
        if self.moz_log is not None:
            files = sorted(glob.glob(self.moz_log + '*'))
            for path in files:
                self.log_pos[path] = os.path.getsize(path)
        self.recording = True
        now = monotonic.monotonic()
        if not self.task['stop_at_onload']:
            self.last_activity = now
        if self.page_loaded is not None:
            self.page_loaded = now
        DesktopBrowser.on_start_recording(self, task)
        logging.debug('Starting measurement')
        task['start_time'] = datetime.utcnow()

    def on_stop_recording(self, task):
        """Notification that we are done with recording"""
        self.recording = False
        DesktopBrowser.on_stop_recording(self, task)
        if self.connected:
            if self.job['pngScreenShot']:
                screen_shot = os.path.join(task['dir'],
                                           task['prefix'] + '_screen.png')
                self.grab_screenshot(screen_shot, png=True)
            else:
                screen_shot = os.path.join(task['dir'],
                                           task['prefix'] + '_screen.jpg')
                self.grab_screenshot(screen_shot, png=False, resize=600)
        # Collect end of test data from the browser
        self.collect_browser_metrics(task)
        # Collect the interactive periods
        interactive = self.execute_js(
            'window.wrappedJSObject.wptagentGetInteractivePeriods();')
        if interactive is not None and len(interactive):
            interactive_file = os.path.join(
                task['dir'], task['prefix'] + '_interactive.json.gz')
            with gzip.open(interactive_file, 'wb', 7) as f_out:
                f_out.write(interactive)
        # Copy the log files
        if self.moz_log is not None:
            task['moz_log'] = os.path.join(task['dir'],
                                           task['prefix'] + '_moz.log')
            files = sorted(glob.glob(self.moz_log + '*'))
            for path in files:
                try:
                    base_name = os.path.basename(path)
                    dest = os.path.join(
                        task['dir'], task['prefix'] + '_' + base_name + '.gz')
                    start_pos = self.log_pos[
                        path] if path in self.log_pos else 0
                    end_pos = os.path.getsize(path)
                    if end_pos > start_pos:
                        length = end_pos - start_pos
                        logging.debug(
                            'Preparing moz log %s (%d bytes from %d)',
                            base_name, length, start_pos)
                        with open(path, 'rb') as f_in:
                            f_in.seek(start_pos)
                            with gzip.open(dest, 'wb', 7) as f_out:
                                while length > 0:
                                    read_bytes = min(length, 1024 * 1024)
                                    buff = f_in.read(read_bytes)
                                    read_bytes = len(buff)
                                    f_out.write(buff)
                                    length -= read_bytes
                except Exception:
                    pass

    def on_start_processing(self, task):
        """Start any processing of the captured data"""
        DesktopBrowser.on_start_processing(self, task)
        # Parse the moz log for the accurate request timings
        request_timings = []
        if 'moz_log' in task:
            from internal.support.firefox_log_parser import FirefoxLogParser
            parser = FirefoxLogParser()
            start_time = task['start_time'].strftime('%Y-%m-%d %H:%M:%S.%f')
            logging.debug('Parsing moz logs relative to %s start time',
                          start_time)
            request_timings = parser.process_logs(task['moz_log'], start_time)
            files = sorted(glob.glob(task['moz_log'] + '*'))
            for path in files:
                try:
                    os.remove(path)
                except Exception:
                    pass
        # Build the request and page data
        if len(request_timings) and task['current_step'] == 1:
            self.adjust_timings(request_timings)
        self.process_requests(request_timings, task)

    def adjust_timings(self, requests):
        """Adjust the request timings to start at zero for the earliest timestamp"""
        timestamps = [
            'dns_start', 'dns_end', 'connect_start', 'connect_end',
            'ssl_start', 'ssl_end', 'start', 'first_byte', 'end'
        ]
        earliest = None
        for request in requests:
            for entry in timestamps:
                if entry in request and request[entry] >= 0:
                    if earliest is None or request[entry] < earliest:
                        earliest = request[entry]
        logging.debug("Adjusting request timings by %0.3f seconds", earliest)
        if earliest is not None and earliest > 0:
            self.start_offset = earliest
            for request in requests:
                for entry in timestamps:
                    if entry in request and request[entry] >= 0:
                        request[entry] -= earliest

    def wait_for_processing(self, task):
        """Wait for any background processing threads to finish"""
        DesktopBrowser.wait_for_processing(self, task)

    def process_command(self, command):
        """Process an individual script command"""
        logging.debug("Processing script command:")
        logging.debug(command)
        if command['command'] == 'navigate':
            self.task['page_data']['URL'] = command['target']
            url = str(command['target']).replace('"', '\"')
            script = 'window.location="{0}";'.format(url)
            script = self.prepare_script_for_record(script)
            self.marionette.execute_script(script)
        elif command['command'] == 'logdata':
            self.task['combine_steps'] = False
            if int(re.search(r'\d+', str(command['target'])).group()):
                logging.debug("Data logging enabled")
                self.task['log_data'] = True
            else:
                logging.debug("Data logging disabled")
                self.task['log_data'] = False
        elif command['command'] == 'combinesteps':
            self.task['log_data'] = True
            self.task['combine_steps'] = True
        elif command['command'] == 'seteventname':
            self.event_name = command['target']
        elif command['command'] == 'exec':
            script = command['target']
            if command['record']:
                script = self.prepare_script_for_record(script)
            self.marionette.execute_script(script)
        elif command['command'] == 'sleep':
            delay = min(
                60,
                max(0, int(re.search(r'\d+', str(command['target'])).group())))
            if delay > 0:
                time.sleep(delay)
        elif command['command'] == 'setabm':
            self.task['stop_at_onload'] = \
                bool('target' in command and int(re.search(r'\d+',
                                                           str(command['target'])).group()) == 0)
        elif command['command'] == 'setactivitytimeout':
            if 'target' in command:
                milliseconds = int(
                    re.search(r'\d+', str(command['target'])).group())
                self.task['activity_time'] = max(
                    0, min(30,
                           float(milliseconds) / 1000.0))
        elif command['command'] == 'setuseragent':
            self.task['user_agent_string'] = command['target']
        elif command['command'] == 'firefoxpref':
            if 'target' in command and 'value' in command:
                self.set_pref(command['target'], command['value'])

    def navigate(self, url):
        """Navigate to the given URL"""
        if self.marionette is not None:
            try:
                self.marionette.navigate(url)
            except Exception as err:
                logging.debug("Error navigating Firefox: %s", str(err))

    def set_pref(self, key, value_str):
        """Set an individual pref value"""
        value = self.get_pref_value(value_str.strip())
        if value is not None:
            try:
                logging.debug('Setting Pref "%s" to %s', key, value_str)
                self.marionette.set_pref(key, value)
            except Exception:
                pass

    def grab_screenshot(self, path, png=True, resize=0):
        """Save the screen shot (png or jpeg)"""
        if self.marionette is not None:
            try:
                data = self.marionette.screenshot(format='binary', full=False)
                if data is not None:
                    resize_string = '' if not resize else '-resize {0:d}x{0:d} '.format(
                        resize)
                    if png:
                        with open(path, 'wb') as image_file:
                            image_file.write(data)
                        if len(resize_string):
                            cmd = '{0} -format png -define png:color-type=2 '\
                                '-depth 8 {1}"{2}"'.format(self.job['image_magick']['mogrify'],
                                                           resize_string, path)
                            logging.debug(cmd)
                            subprocess.call(cmd, shell=True)
                    else:
                        tmp_file = path + '.png'
                        with open(tmp_file, 'wb') as image_file:
                            image_file.write(data)
                        command = '{0} "{1}" {2}-quality {3:d} "{4}"'.format(
                            self.job['image_magick']['convert'], tmp_file,
                            resize_string, self.job['imageQuality'], path)
                        logging.debug(command)
                        subprocess.call(command, shell=True)
                        if os.path.isfile(tmp_file):
                            try:
                                os.remove(tmp_file)
                            except Exception:
                                pass
            except Exception as err:
                logging.debug('Exception grabbing screen shot: %s', str(err))

    def process_requests(self, request_timings, task):
        """Convert all of the request and page events into the format needed for WPT"""
        result = {}
        result['requests'] = self.merge_requests(request_timings)
        result['pageData'] = self.calculate_page_stats(result['requests'])
        devtools_file = os.path.join(
            task['dir'], task['prefix'] + '_devtools_requests.json.gz')
        with gzip.open(devtools_file, 'wb', 7) as f_out:
            json.dump(result, f_out)

    def get_empty_request(self, request_id, url):
        """Return and empty, initialized request"""
        parts = urlparse.urlsplit(url)
        request = {
            'type': 3,
            'id': request_id,
            'request_id': request_id,
            'ip_addr': '',
            'full_url': url,
            'is_secure': 1 if parts.scheme == 'https' else 0,
            'method': '',
            'host': parts.netloc,
            'url': parts.path,
            'responseCode': -1,
            'load_start': -1,
            'load_ms': -1,
            'ttfb_ms': -1,
            'dns_start': -1,
            'dns_end': -1,
            'dns_ms': -1,
            'connect_start': -1,
            'connect_end': -1,
            'connect_ms': -1,
            'ssl_start': -1,
            'ssl_end': -1,
            'ssl_ms': -1,
            'bytesIn': 0,
            'bytesOut': 0,
            'objectSize': 0,
            'initiator': '',
            'initiator_line': '',
            'initiator_column': '',
            'server_rtt': None,
            'headers': {
                'request': [],
                'response': []
            },
            'score_cache': -1,
            'score_cdn': -1,
            'score_gzip': -1,
            'score_cookies': -1,
            'score_keep-alive': -1,
            'score_minify': -1,
            'score_combine': -1,
            'score_compress': -1,
            'score_etags': -1,
            'gzip_total': None,
            'gzip_save': None,
            'minify_total': None,
            'minify_save': None,
            'image_total': None,
            'image_save': None,
            'cache_time': None,
            'cdn_provider': None,
            'server_count': None,
            'socket': -1
        }
        if len(parts.query):
            request['url'] += '?' + parts.query
        return request

    def get_header_value(self, headers, name):
        """Return the value for the given header"""
        value = ''
        name = name.lower()
        for header in headers:
            pos = header.find(':')
            if pos > 0:
                key = header[0:pos].lower()
                if key.startswith(name):
                    val = header[pos + 1:].strip()
                    if len(value):
                        value += '; '
                    value += val
        return value

    def merge_requests(self, request_timings):
        """Merge the requests from the extension and log files"""
        requests = []
        # Start with the requests reported from the extension
        for req_id in self.requests:
            try:
                req = self.requests[req_id]
                if req['from_net'] and 'start' in req and 'url' in req:
                    request = self.get_empty_request(req['id'], req['url'])
                    if 'ip' in req:
                        request['ip_addr'] = req['ip']
                    if 'method' in req:
                        request['method'] = req['method']
                    if 'status' in req:
                        request['responseCode'] = req['status']
                    if 'type' in req:
                        request['requestType'] = req['type']
                    if 'request_headers' in req:
                        for header in req['request_headers']:
                            if 'name' in header and 'value' in header:
                                header_text = '{0}: {1}'.format(
                                    header['name'], header['value'])
                                request['bytesOut'] += len(header_text) + 2
                                request['headers']['request'].append(
                                    header_text)
                    if 'status_line' in req:
                        request['bytesIn'] += len(req['status_line']) + 2
                        request['headers']['response'].append(
                            req['status_line'])
                    if 'response_headers' in req:
                        for header in req['response_headers']:
                            if 'name' in header and 'value' in header:
                                try:
                                    header_text = '{0}: {1}'.format(
                                        header['name'], header['value'])
                                    request['bytesIn'] += len(header_text) + 2
                                    request['headers']['response'].append(
                                        header_text)
                                except Exception:
                                    pass
                    if 'created' in req:
                        request['created'] = req['created']
                    request['load_start'] = int(round(req['start'] * 1000.0))
                    if 'first_byte' in req:
                        ttfb = int(
                            round((req['first_byte'] - req['start']) * 1000.0))
                        request['ttfb_ms'] = max(0, ttfb)
                    if 'end' in req:
                        load_time = int(
                            round((req['end'] - req['start']) * 1000.0))
                        request['load_ms'] = max(0, load_time)
                    size = self.get_header_value(
                        request['headers']['response'], 'Content-Length')
                    if len(size):
                        request['bytesIn'] += int(
                            re.search(r'\d+', str(size)).group())
                    requests.append(request)
            except Exception:
                pass
        # Overwrite them with the same requests from the logs
        for request in requests:
            for req in request_timings:
                try:
                    if 'claimed' not in req and 'url' in req and 'full_url' in request \
                            and 'start' in req and request['full_url'] == req['url']:
                        req['claimed'] = True
                        self.populate_request(request, req)
                except Exception:
                    pass
        # Add any events from the logs that weren't reported by the extension
        for req in request_timings:
            try:
                if 'claimed' not in req and 'url' in req and 'start' in req:
                    request = self.get_empty_request(req['id'], req['url'])
                    self.populate_request(request, req)
                    requests.append(request)
            except Exception:
                pass
        # parse values out of the headers
        for request in requests:
            try:
                value = self.get_header_value(request['headers']['response'],
                                              'Expires')
                if value:
                    request['expires'] = value
                value = self.get_header_value(request['headers']['response'],
                                              'Cache-Control')
                if value:
                    request['cacheControl'] = value
                value = self.get_header_value(request['headers']['response'],
                                              'Content-Type')
                if value:
                    request['contentType'] = value
                value = self.get_header_value(request['headers']['response'],
                                              'Content-Encoding')
                if value:
                    request['contentEncoding'] = value
                value = self.get_header_value(request['headers']['response'],
                                              'Content-Length')
                if value:
                    request['objectSize'] = value
            except Exception:
                pass
        requests.sort(key=lambda x: x['load_start'])
        return requests

    def populate_request(self, request, log_request):
        """Populate a request object from the log request values"""
        request['load_start'] = int(log_request['start'] * 1000)
        if 'status' in log_request:
            request['responseCode'] = log_request['status']
        if 'dns_start' in log_request and log_request['dns_start'] >= 0:
            request['dns_start'] = int(log_request['dns_start'] * 1000)
        if 'dns_end' in log_request and log_request['dns_end'] >= 0:
            request['dns_end'] = int(round(log_request['dns_end'] * 1000.0))
        if 'connect_start' in log_request and log_request['connect_start'] >= 0:
            request['connect_start'] = int(log_request['connect_start'] * 1000)
        if 'connect_end' in log_request and log_request['connect_end'] >= 0:
            request['connect_end'] = int(
                round(log_request['connect_end'] * 1000.0))
        if 'ssl_start' in log_request and log_request['ssl_start'] >= 0:
            request['ssl_start'] = int(log_request['ssl_start'] * 1000)
        if 'ssl_end' in log_request and log_request['ssl_end'] >= 0:
            request['ssl_end'] = int(round(log_request['ssl_end'] * 1000.0))
        if 'connection' in log_request:
            request['socket'] = log_request['connection']
        request['load_start'] = int(round(log_request['start'] * 1000.0))
        if 'first_byte' in log_request:
            request['ttfb_ms'] = int(round((log_request['first_byte'] - \
                                            log_request['start']) * 1000.0))
        if 'end' in log_request:
            request['load_ms'] = int(round((log_request['end'] - \
                                            log_request['start']) * 1000.0))
        if 'bytes_in' in log_request:
            request['bytesIn'] = log_request['bytes_in']
        if 'request_headers' in log_request:
            request['headers']['request'] = list(
                log_request['request_headers'])
        if 'response_headers' in log_request:
            request['headers']['response'] = list(
                log_request['response_headers'])

    def calculate_page_stats(self, requests):
        """Calculate the page-level stats"""
        page = {'loadTime': 0,
                'docTime': 0,
                'fullyLoaded': 0,
                'bytesOut': 0,
                'bytesOutDoc': 0,
                'bytesIn': 0,
                'bytesInDoc': 0,
                'requests': len(requests),
                'requestsDoc': 0,
                'responses_200': 0,
                'responses_404': 0,
                'responses_other': 0,
                'result': 0,
                'testStartOffset': 0,
                'cached': 1 if self.task['cached'] else 0,
                'optimization_checked': 0,
                'start_epoch': int((self.task['start_time'] - \
                                    datetime.utcfromtimestamp(0)).total_seconds())
               }
        if 'loaded' in self.page:
            page['loadTime'] = int(round(self.page['loaded'] * 1000.0))
            page['docTime'] = page['loadTime']
            page['loadEventStart'] = page['loadTime']
            page['loadEventEnd'] = page['loadTime']
        if 'DOMContentLoaded' in self.page:
            page['domContentLoadedEventStart'] = int(
                round(self.page['DOMContentLoaded'] * 1000.0))
            page['domContentLoadedEventEnd'] = page[
                'domContentLoadedEventStart']

        main_request = None
        index = 0
        for request in requests:
            if request['load_ms'] >= 0:
                end_time = request['load_start'] + request['load_ms']
                if end_time > page['fullyLoaded']:
                    page['fullyLoaded'] = end_time
                if end_time <= page['loadTime']:
                    page['requestsDoc'] += 1
                    page['bytesInDoc'] += request['bytesIn']
                    page['bytesOutDoc'] += request['bytesOut']
            page['bytesIn'] += request['bytesIn']
            page['bytesOut'] += request['bytesOut']
            if request['responseCode'] == 200:
                page['responses_200'] += 1
            elif request['responseCode'] == 404:
                page['responses_404'] += 1
                page['result'] = 99999
            elif request['responseCode'] > -1:
                page['responses_other'] += 1
            if main_request is None and \
                    (request['responseCode'] == 200 or request['responseCode'] == 304):
                main_request = request['id']
                request['is_base_page'] = True
                page['final_base_page_request'] = index
                page['final_base_page_request_id'] = main_request
                page['final_url'] = request['full_url']
                if 'URL' not in self.task['page_data']:
                    self.task['page_data']['URL'] = page['final_url']
                if request['ttfb_ms'] >= 0:
                    page['TTFB'] = request['load_start'] + request['ttfb_ms']
                if request['ssl_end'] >= request['ssl_start'] and \
                        request['ssl_start'] >= 0:
                    page['basePageSSLTime'] = int(round(request['ssl_end'] - \
                                                        request['ssl_start']))
        if page['responses_200'] == 0 and len(requests):
            if 'responseCode' in requests[0]:
                page['result'] = requests[0]['responseCode']
            else:
                page['result'] = 12999
        self.task['page_result'] = page['result']
        return page
示例#11
0
import os
import sys
import fnmatch

from marionette_driver.marionette import Marionette

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

client = Marionette(host='localhost', port=2828)
client.start_session()

client.set_context(Marionette.CONTEXT_CHROME)

with open(os.path.join(BASE_DIR, 'jasmine.js')) as f:
    client.execute_script(f.read(), sandbox='tests', new_sandbox=False)

with open(os.path.join(BASE_DIR, 'boot.js')) as f:
    client.execute_script(f.read(), sandbox='tests', new_sandbox=False)

test_dir = sys.argv[1]
for root, dirnames, filenames in os.walk(test_dir):
    for filename in fnmatch.filter(filenames, 'test*.js'):
        with open(os.path.join(root, filename)) as f:
            client.execute_script(f.read(), sandbox='tests', new_sandbox=False)

specs = client.execute_script("""
runSpecs();
return jsApiReporter.specs();
""",
                              sandbox='tests',
                              new_sandbox=False)
示例#12
0
#!/usr/bin/python2.7
#
# Script to work around Marionette bug 879816 (cannot click the modal 'ok' button
# following clicking something else).
#
from marionette_driver.marionette import Marionette
marionette = Marionette(host='localhost', port=2828)
marionette.start_session()
marionette.switch_to_frame()
marionette.execute_script(
    "document.getElementById('modal-dialog-prompt-ok').click();")
示例#13
0
    def run_tests(self):
        """
        Generate the PGO profile data
        """
        from mozhttpd import MozHttpd
        from mozprofile import Preferences
        from mozdevice import ADBDevice, ADBProcessError, ADBTimeoutError
        from six import string_types
        from marionette_driver.marionette import Marionette

        app = self.query_package_name()

        IP = '10.0.2.2'
        PORT = 8888

        PATH_MAPPINGS = {
            '/js-input/webkit/PerformanceTests':
            'third_party/webkit/PerformanceTests',
        }

        dirs = self.query_abs_dirs()
        topsrcdir = os.path.join(dirs['abs_work_dir'], 'src')
        adb = self.query_exe('adb')

        path_mappings = {
            k: os.path.join(topsrcdir, v)
            for k, v in PATH_MAPPINGS.items()
        }
        httpd = MozHttpd(port=PORT,
                         docroot=os.path.join(topsrcdir, "build", "pgo"),
                         path_mappings=path_mappings)
        httpd.start(block=False)

        profile_data_dir = os.path.join(topsrcdir, 'testing', 'profiles')
        with open(os.path.join(profile_data_dir, 'profiles.json'), 'r') as fh:
            base_profiles = json.load(fh)['profileserver']

        prefpaths = [
            os.path.join(profile_data_dir, profile, 'user.js')
            for profile in base_profiles
        ]

        prefs = {}
        for path in prefpaths:
            prefs.update(Preferences.read_prefs(path))

        interpolation = {
            "server": "%s:%d" % httpd.httpd.server_address,
            "OOP": "false"
        }
        for k, v in prefs.items():
            if isinstance(v, string_types):
                v = v.format(**interpolation)
            prefs[k] = Preferences.cast(v)

        outputdir = self.config.get('output_directory', '/sdcard')
        jarlog = posixpath.join(outputdir, 'en-US.log')
        profdata = posixpath.join(outputdir, 'default.profraw')

        env = {}
        env["XPCOM_DEBUG_BREAK"] = "warn"
        env["MOZ_IN_AUTOMATION"] = "1"
        env["MOZ_JAR_LOG_FILE"] = jarlog
        env["LLVM_PROFILE_FILE"] = profdata

        adbdevice = ADBDevice(adb=adb, device='emulator-5554')

        try:
            # Run Fennec a first time to initialize its profile
            driver = Marionette(
                app='fennec',
                package_name=app,
                adb_path=adb,
                bin="target.apk",
                prefs=prefs,
                connect_to_running_emulator=True,
                startup_timeout=1000,
                env=env,
            )
            driver.start_session()

            # Now generate the profile and wait for it to complete
            for page in PAGES:
                driver.navigate("http://%s:%d/%s" % (IP, PORT, page))
                timeout = 2
                if 'Speedometer/index.html' in page:
                    # The Speedometer test actually runs many tests internally in
                    # javascript, so it needs extra time to run through them. The
                    # emulator doesn't get very far through the whole suite, but
                    # this extra time at least lets some of them process.
                    timeout = 360
                time.sleep(timeout)

            driver.set_context("chrome")
            driver.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
                    .createInstance(Components.interfaces.nsISupportsPRBool);
                Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null);
                return cancelQuit.data;
            """)
            driver.execute_script("""
                Components.utils.import("resource://gre/modules/Services.jsm");
                Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit)
            """)

            # There is a delay between execute_script() returning and the profile data
            # actually getting written out, so poll the device until we get a profile.
            for i in range(50):
                try:
                    localprof = '/builds/worker/workspace/default.profraw'
                    adbdevice.pull(profdata, localprof)
                    stats = os.stat(localprof)
                    if stats.st_size == 0:
                        # The file may not have been fully written yet, so retry until we
                        # get actual data.
                        time.sleep(2)
                    else:
                        break
                except ADBProcessError:
                    # The file may not exist at all yet, which would raise an
                    # ADBProcessError, so retry.
                    time.sleep(2)
            else:
                raise Exception("Unable to pull default.profraw")
            adbdevice.pull(jarlog, '/builds/worker/workspace/en-US.log')
        except ADBTimeoutError:
            self.fatal('INFRA-ERROR: Failed with an ADBTimeoutError',
                       EXIT_STATUS_DICT[TBPL_RETRY])

        # We normally merge as part of a GENERATED_FILES step in the profile-use
        # build, but Android runs sometimes result in a truncated profile. We do
        # a merge here to make sure the data isn't corrupt so we can retry the
        # 'run' task if necessary.
        merge_cmd = [
            '/builds/worker/workspace/build/clang/bin/llvm-profdata',
            'merge',
            '/builds/worker/workspace/default.profraw',
            '-o',
            '/builds/worker/workspace/merged.profraw',
        ]
        rc = subprocess.call(merge_cmd)
        if rc != 0:
            self.fatal(
                'INFRA-ERROR: Failed to merge profile data. Corrupt profile?',
                EXIT_STATUS_DICT[TBPL_RETRY])

        # tarfile doesn't support xz in this version of Python
        tar_cmd = [
            'tar',
            '-acvf',
            '/builds/worker/artifacts/profdata.tar.xz',
            '-C',
            '/builds/worker/workspace',
            'merged.profraw',
            'en-US.log',
        ]
        subprocess.check_call(tar_cmd)

        httpd.stop()
示例#14
0
    passwordLogin.send_keys(config.get('Login', 'pass'))
    # Click on the Log in button to connect
    client.find_element(By.ID, 'wp-submit').click()
    time.sleep(1)
    Wait(client).until(logged_in)
except:
    print "Already logged"
# Move to the term
term = args.search
# encode the term and change the space ('%20') in a '+'
term = urllib.quote_plus(term, safe='')

client.navigate("https://translate.wordpress.org/consistency?search=" + term + "&set=" + args.lang + "%2Fdefault")
# Remove the strings different from our
removeOtherStrings = "var right = document.querySelectorAll('table td:nth-child(2) .string');for (var i=0; i<right.length; i++){if(right[i].innerHTML!=='" + cgi.escape(args.remove.replace("'","\\'")) + "') {td = right[i].parentNode;tr = td.parentNode;tr.outerHTML=''}}"
result = client.execute_script(removeOtherStrings)
# Force to open the link in another tab with a little hack in js
addTarget = "var anchors = document.querySelectorAll('table td:nth-child(2) .meta a');for (var i=0; i<anchors.length; i++){anchors[i].setAttribute('target', '_blank');}"
result = client.execute_script(addTarget)
# Open all the links
openPages = client.find_elements(By.CSS_SELECTOR, 'table td:nth-child(2) .meta a')
print('Find ' + str(len(openPages)) + ' wrong strings for ' + args.search + ' with -> ' + args.remove)
i = 0
j = 0
for openPage in openPages:
    original_window = client.current_window_handle
    openPage.click()
    # Wait page load, glotpress is very slow
    time.sleep(1.5)
    all_tab = client.window_handles
    if all_tab[-1] != original_window:
class MuletReftest(RefTest):
    build_type = "mulet"
    marionette = None

    def __init__(self, marionette_args):
        RefTest.__init__(self)
        self.last_test = os.path.basename(__file__)
        self.marionette_args = marionette_args
        self.profile = None
        self.runner = None
        self.test_script = os.path.join(here, 'b2g_start_script.js')
        self.timeout = None

    def run_marionette_script(self):
        self.marionette = Marionette(**self.marionette_args)
        assert (self.marionette.wait_for_port())
        self.marionette.start_session()
        if self.build_type == "mulet":
            self._wait_for_homescreen(timeout=300)
            self._unlockScreen()
        self.marionette.set_context(self.marionette.CONTEXT_CHROME)

        if os.path.isfile(self.test_script):
            f = open(self.test_script, 'r')
            self.test_script = f.read()
            f.close()
        self.marionette.execute_script(self.test_script)

    def run_tests(self, tests, options):
        manifests = self.resolver.resolveManifests(options, tests)

        self.profile = self.create_profile(options,
                                           manifests,
                                           profile_to_clone=options.profile)
        env = self.buildBrowserEnv(options, self.profile.profile)
        kp_kwargs = {
            'processOutputLine': [self._on_output],
            'onTimeout': [self._on_timeout],
            'kill_on_timeout': False
        }

        if not options.debugger:
            if not options.timeout:
                if mozinfo.info['debug']:
                    options.timeout = 420
                else:
                    options.timeout = 300
            self.timeout = options.timeout + 30.0

        log.info("%s | Running tests: start.", os.path.basename(__file__))
        cmd, args = self.build_command_line(
            options.app,
            ignore_window_size=options.ignoreWindowSize,
            browser_arg=options.browser_arg)
        self.runner = FirefoxRunner(profile=self.profile,
                                    binary=cmd,
                                    cmdargs=args,
                                    env=env,
                                    process_class=ProcessHandler,
                                    process_args=kp_kwargs,
                                    symbols_path=options.symbolsPath)

        status = 0
        try:
            self.runner.start(outputTimeout=self.timeout)
            log.info("%s | Application pid: %d", os.path.basename(__file__),
                     self.runner.process_handler.pid)

            # kick starts the reftest harness
            self.run_marionette_script()
            status = self.runner.wait()
        finally:
            self.runner.check_for_crashes(test_name=self.last_test)
            self.runner.cleanup()

        if status > 0:
            log.testFail("%s | application terminated with exit code %s",
                         self.last_test, status)
        elif status < 0:
            log.info("%s | application killed with signal %s", self.last_test,
                     -status)

        log.info("%s | Running tests: end.", os.path.basename(__file__))
        return status

    def create_profile(self, options, manifests, profile_to_clone=None):
        profile = RefTest.createReftestProfile(
            self, options, manifests, profile_to_clone=profile_to_clone)

        prefs = {}
        # Turn off the locale picker screen
        prefs["browser.firstrun.show.localepicker"] = False
        if not self.build_type == "mulet":
            # FIXME: With Mulet we can't set this values since Gaia won't launch
            prefs["b2g.system_startup_url"] = \
                    "app://test-container.gaiamobile.org/index.html"
            prefs["b2g.system_manifest_url"] = \
                    "app://test-container.gaiamobile.org/manifest.webapp"
        # Make sure we disable system updates
        prefs["app.update.enabled"] = False
        prefs["app.update.url"] = ""
        prefs["app.update.url.override"] = ""
        # Disable webapp updates
        prefs["webapps.update.enabled"] = False
        # Disable tiles also
        prefs["browser.newtabpage.directory.source"] = ""
        prefs["browser.newtabpage.directory.ping"] = ""
        prefs["dom.ipc.tabs.disabled"] = False
        prefs["dom.mozBrowserFramesEnabled"] = True
        prefs["font.size.inflation.emPerLine"] = 0
        prefs["font.size.inflation.minTwips"] = 0
        prefs[
            "network.dns.localDomains"] = "app://test-container.gaiamobile.org"
        prefs["reftest.browser.iframe.enabled"] = False
        prefs["reftest.remote"] = False
        # Set a future policy version to avoid the telemetry prompt.
        prefs["toolkit.telemetry.prompted"] = 999
        prefs["toolkit.telemetry.notifiedOptOut"] = 999

        # Set the extra prefs.
        profile.set_preferences(prefs)
        return profile

    def build_command_line(self,
                           app,
                           ignore_window_size=False,
                           browser_arg=None):
        cmd = os.path.abspath(app)
        args = ['-marionette']

        if browser_arg:
            args += [browser_arg]

        if not ignore_window_size:
            args.extend(['--screen', '800x1000'])

        if self.build_type == "mulet":
            args += ['-chrome', 'chrome://b2g/content/shell.html']
        return cmd, args

    def _on_output(self, line):
        sys.stdout.write("%s\n" % line)
        sys.stdout.flush()

        # TODO use structured logging
        if "TEST-START" in line and "|" in line:
            self.last_test = line.split("|")[1].strip()

    def _on_timeout(self):
        msg = "%s | application timed out after %s seconds with no output"
        log.testFail(msg % (self.last_test, self.timeout))

        # kill process to get a stack
        self.runner.stop(sig=signal.SIGABRT)

    def _unlockScreen(self):
        self.marionette.set_context(self.marionette.CONTEXT_CONTENT)
        self.marionette.import_script(
            os.path.abspath(
                os.path.join(__file__, os.path.pardir, "gaia_lock_screen.js")))
        self.marionette.switch_to_frame()
        self.marionette.execute_async_script('GaiaLockScreen.unlock()')

    def _wait_for_homescreen(self, timeout):
        log.info("Waiting for home screen to load")
        Wait(self.marionette, timeout).until(
            expected.element_present(By.CSS_SELECTOR,
                                     '#homescreen[loading-state=false]'))
示例#16
0
class MarionetteHelper:
    """ Helper for starting firefox and for remote browsing

    """

    def __init__(self, firefox_path, logger=None):
        self.logger = logger  # type: logging.Logger
        self.client = None  # type: Marionette
        self.ffpopen = None  # type: subprocess.Popen
        self.ffpath = firefox_path  # type: str
        if logger is None:
            self.logger = logging.getLogger("MarionetteHelper")
        self.logger.debug("Marionette helper init done")

    def _open_session(self, host='localhost', port=2828):
        """ Opens the session for marionette"""
        caps = {u'acceptInsecureCerts': True, }
        self.client = Marionette(host, port=port)
        self.client.start_session(capabilities=caps)

    def run_firefox(self):
        """ Start the firefox process"""
        self.logger.debug("Starting firefox process")
        self.ffpopen = subprocess.Popen([self.ffpath, "-marionette"])
        self.logger.debug("Opening marionette session")
        self._open_session()

    def quit_firefox(self):
        """ Close the firefox process and close marionette session"""
        #self.logger.debug("Closing firefox")
        #self.client._send_message("Marionette:Quit")
        self.client._request_in_app_shutdown("eForceQuit")
        self.client.delete_session(False)
        self.client.cleanup()
        self.client = None # reset client state
        #try:
        #    self.client.close()  # try to close the window anyway
        #except InvalidSessionIdException:
        #    pass
        #except socket.error:
        #    pass
        #finally:
        #    try:
        #        self.logger.debug("Closing marionette session")
        #        self.client.delete_session(False)  # close client session
        #    except InvalidSessionIdException:
        #        pass
        #    except socket.error:
        #        pass
        #    self.client = None  # reset client state
        #self.logger.debug("Waiting for firefox to close")
        #for _ in range(3):  # give the process 3 seconds to terminate
        #    time.sleep(1)
        #    self.ffpopen.poll()
        #    if self.ffpopen.returncode is not None:
        #        break
        #self.ffpopen.poll()
        #if self.ffpopen.returncode is None:
        #    self.logger.warning("Firefox not closed in time, killing it!")
        #    self.ffpopen.kill()  # process was not quit in time, kill it
        #self.ffpopen = None  # reset popen state
        #self.logger.debug("Firefox is closed")

    def ___get_client(self):
        """ Returns the internal marionette client object"""
        return self.client

    def navigate_to_url(self, url):
        """ Open an url in format of http[s]://example.com"""
        try:
            if "http" not in url:
                url = "http://" + url
            self.client.navigate(url)
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def back(self):
        """ Go a page backward"""
        try:
            self.client.go_back()
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def forward(self):
        """ Go a page forward"""
        try:
            self.client.go_forward()
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def follow_link(self, index=0):
        """ Click on a link"""
        try:
            links = self.client.find_elements(By.TAG_NAME, "a")
            links[index].click()
        except ElementNotVisibleException:
            self.logger.warning("Error: Element not visible")
            return False
        except ElementNotSelectableException:
            self.logger.warning("Error: Element not selectable")
            return False
        except ElementNotAccessibleException:
            self.logger.warning("Error: Element not accessible")
            return False
        except ElementNotInteractableException:
            self.logger.warning("Error: Element not interactable")
            return False
        except NoSuchElementException:
            self.logger.warning("Error: Element does not exist")
            return False
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except IndexError:
            self.logger.warning("Error: Out of bound")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def click_element_by_class_name(self, html_class_name):
        """ Click on first element via class name"""
        try:
            e = self.client.find_element(By.CLASS_NAME, html_class_name)
            e.click()
        except ElementNotVisibleException:
            self.logger.warning("Error: Element not visible")
            return False
        except ElementNotSelectableException:
            self.logger.warning("Error: Element not selectable")
            return False
        except ElementNotAccessibleException:
            self.logger.warning("Error: Element not accessible")
            return False
        except ElementNotInteractableException:
            self.logger.warning("Error: Element not interactable")
            return False
        except NoSuchElementException:
            self.logger.warning("Error: Element does not exist")
            return False
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def click_element_by_css_selector(self, css_selector):
        """ Click on first element via css selector"""
        try:
            e = self.client.find_element(By.CSS_SELECTOR, css_selector)
            e.click()
        except ElementNotVisibleException:
            self.logger.warning("Error: Element not visible")
            return False
        except ElementNotSelectableException:
            self.logger.warning("Error: Element not selectable")
            return False
        except ElementNotAccessibleException:
            self.logger.warning("Error: Element not accessible")
            return False
        except ElementNotInteractableException:
            self.logger.warning("Error: Element not interactable")
            return False
        except NoSuchElementException:
            self.logger.warning("Error: Element does not exist")
            return False
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def click_element_by_id(self, html_id):
        """ Click on first element via element id"""
        try:
            e = self.client.find_element(By.ID, html_id)
            e.click()
        except ElementNotVisibleException:
            self.logger.warning("Error: Element not visible")
            return False
        except ElementNotSelectableException:
            self.logger.warning("Error: Element not selectable")
            return False
        except ElementNotAccessibleException:
            self.logger.warning("Error: Element not accessible")
            return False
        except ElementNotInteractableException:
            self.logger.warning("Error: Element not interactable")
            return False
        except NoSuchElementException:
            self.logger.warning("Error: Element does not exist")
            return False
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def click_element_by_name(self, html_name):
        """ Click on first element via element name"""
        try:
            e = self.client.find_element(By.NAME, html_name)
            e.click()
        except ElementNotVisibleException:
            self.logger.warning("Error: Element not visible")
            return False
        except ElementNotSelectableException:
            self.logger.warning("Error: Element not selectable")
            return False
        except ElementNotAccessibleException:
            self.logger.warning("Error: Element not accessible")
            return False
        except ElementNotInteractableException:
            self.logger.warning("Error: Element not interactable")
            return False
        except NoSuchElementException:
            self.logger.warning("Error: Element does not exist")
            return False
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def click_element_by_tag_name(self, html_tag_name):
        """ Click on first element via tag name"""
        try:
            e = self.client.find_element(By.TAG_NAME, html_tag_name)
            e.click()
        except ElementNotVisibleException:
            self.logger.warning("Error: Element not visible")
            return False
        except ElementNotSelectableException:
            self.logger.warning("Error: Element not selectable")
            return False
        except ElementNotAccessibleException:
            self.logger.warning("Error: Element not accessible")
            return False
        except ElementNotInteractableException:
            self.logger.warning("Error: Element not interactable")
            return False
        except NoSuchElementException:
            self.logger.warning("Error: Element does not exist")
            return False
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def click_element_by_xpath(self, xpath):
        """ Click on first element via xpath"""
        try:
            e = self.client.find_element(By.XPATH, xpath)
            e.click()
        except ElementNotVisibleException:
            self.logger.warning("Error: Element not visible")
            return False
        except ElementNotSelectableException:
            self.logger.warning("Error: Element not selectable")
            return False
        except ElementNotAccessibleException:
            self.logger.warning("Error: Element not accessible")
            return False
        except ElementNotInteractableException:
            self.logger.warning("Error: Element not interactable")
            return False
        except NoSuchElementException:
            self.logger.warning("Error: Element does not exist")
            return False
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def click_element_by_link_text(self, html_link_text):
        """ Click on first element via link text"""
        try:
            e = self.client.find_element(By.LINK_TEXT, html_link_text)
            e.click()
        except ElementNotVisibleException:
            self.logger.warning("Error: Element not visible")
            return False
        except ElementNotSelectableException:
            self.logger.warning("Error: Element not selectable")
            return False
        except ElementNotAccessibleException:
            self.logger.warning("Error: Element not accessible")
            return False
        except ElementNotInteractableException:
            self.logger.warning("Error: Element not interactable")
            return False
        except NoSuchElementException:
            self.logger.warning("Error: Element does not exist")
            return False
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        except InsecureCertificateException:
            self.logger.warning("Warning: Insecure Certificate")
            return True
        except UnknownException as e:
            if "Reached error page" in str(e):
                self.logger.warning("Reached error page, ignoring...")
            else: # reraise, something very unexpected happened here
                t, v, tb = sys.exc_info()
                raise t, v, tb
            return False
        return True

    def send_keys_to_element_by_name(self, name, text):
        """ Sends text to an element via name"""
        try:
            e = self.client.find_element(By.NAME, name)
            e.send_keys(text)
        except ElementNotVisibleException:
            self.logger.warning("Error: Element not visible")
            return False
        except ElementNotSelectableException:
            self.logger.warning("Error: Element not selectable")
            return False
        except ElementNotAccessibleException:
            self.logger.warning("Error: Element not accessible")
            return False
        except ElementNotInteractableException:
            self.logger.warning("Error: Element not interactable")
            return False
        except NoSuchElementException:
            self.logger.warning("Error: Element does not exist")
            return False
        except TimeoutException:
            self.logger.warning("Error: Timeout")
            return False
        return True

    def select_window(self, index):
        """ Switch window via index"""
        try:
            self.client.switch_to_window(self.client.window_handles[index])
        except NoSuchWindowException:
            self.logger.warning("Error: Window does not exist")
            return False
        return True

    def close_window(self):
        """ Close the current window"""
        self.client.close()  # this won't close the last window, call quit_firefox instead

    def get_current_window_index(self):
        """ Get current windows index"""
        return self.client.window_handles.index(self.client.current_window_handle)

    def new_tab(self):
        """ Open a new empty tab"""
        with self.client.using_context("chrome"):
            self.client.find_element(By.ID, "menu_newNavigatorTab").click()

    def new_window(self):
        """ Open a new empty window"""
        with self.client.using_context("chrome"):
            self.client.execute_script("window.open();")

    def close_tab(self):
        """ Close the current tab"""
        self.close_window()  # basically the same as close windows
#!/usr/bin/python2.7
#
# Script to work around Marionette bug 879816 (cannot click the modal 'ok' button
# following clicking something else).
#
from marionette_driver.marionette import Marionette
marionette = Marionette(host='localhost', port=2828)
marionette.start_session()
marionette.switch_to_frame()
marionette.execute_script("document.getElementById('modal-dialog-prompt-ok').click();")
示例#18
0
    passwordLogin.send_keys(config.get('Login', 'pass'))
    # Click on the Log in button to connect
    client.find_element(By.ID, 'wp-submit').click()
    time.sleep(1)
    Wait(client).until(logged_in)
except:
    print "Already logged"
# Move to the term
term = args.search
# encode the term and change the space ('%20') in a '+'
term = urllib.quote_plus(term, safe='')

client.navigate("https://translate.wordpress.org/consistency?search=" + term + "&set=" + args.lang + "%2Fdefault")
# Remove the strings different from our
removeOtherStrings = "var right = document.querySelectorAll('table td:nth-child(2) .string');for (var i=0; i<right.length; i++){if(right[i].innerHTML!=='" + cgi.escape(args.remove.replace("'","\\'")) + "') {td = right[i].parentNode;tr = td.parentNode;tr.outerHTML=''}}"
result = client.execute_script(removeOtherStrings)
# Force to open the link in another tab with a little hack in js
addTarget = "var anchors = document.querySelectorAll('table td:nth-child(2) .meta a');for (var i=0; i<anchors.length; i++){anchors[i].setAttribute('target', '_blank');}"
result = client.execute_script(addTarget)
# Open all the links
openPages = client.find_elements(By.CSS_SELECTOR, 'table td:nth-child(2) .meta a')
print('Find ' + str(len(openPages)) + ' wrong strings for ' + args.search + ' with -> ' + args.remove)
i = 0
j = 0
for openPage in openPages:
    original_window = client.current_window_handle
    openPage.click()
    # Wait page load, glotpress is very slow
    time.sleep(1.5)
    all_tab = client.window_handles
    if all_tab[-1] != original_window: