Esempio n. 1
0
def get_dm(marionette=None,**kwargs):
    dm_type = os.environ.get('DM_TRANS', 'adb')
    if marionette and hasattr(marionette.runner, 'device'):
        return marionette.runner.app_ctx.dm
    elif marionette and marionette.device_serial and dm_type == 'adb':
        return mozdevice.DeviceManagerADB(deviceSerial=marionette.device_serial, **kwargs)
    else:
        if dm_type == 'adb':
            return mozdevice.DeviceManagerADB(**kwargs)
        elif dm_type == 'sut':
            host = os.environ.get('TEST_DEVICE')
            if not host:
                raise Exception('Must specify host with SUT!')
            return mozdevice.DeviceManagerSUT(host=host)
        else:
            raise Exception('Unknown device manager type: %s' % dm_type)
Esempio n. 2
0
    def __init__(self,
                 sources=None,
                 dm_type='adb',
                 host=None,
                 device_serial=None,
                 **kwargs):
        B2GVersion.__init__(self, sources, **kwargs)

        if dm_type == 'adb':
            dm = mozdevice.DeviceManagerADB(deviceSerial=device_serial)
        elif dm_type == 'sut':
            if not host:
                raise Exception('A host for SUT must be supplied.')
            dm = mozdevice.DeviceManagerSUT(host=host)
        else:
            raise Exception('Unknown device manager type: %s' % dm_type)

        if not sources:
            path = 'system/sources.xml'
            if dm.fileExists(path):
                sources = StringIO(dm.pullFile(path))
            else:
                self.info('Unable to find %s' % path)

        tempdir = tempfile.mkdtemp()
        for ini in ('application', 'platform'):
            with open(os.path.join(tempdir, '%s.ini' % ini), 'w') as f:
                f.write(dm.pullFile('/system/b2g/%s.ini' % ini))
                f.flush()
        self.get_gecko_info(tempdir)
        mozfile.remove(tempdir)

        for path in ['/system/b2g', '/data/local']:
            path += '/webapps/settings.gaiamobile.org/application.zip'
            if dm.fileExists(path):
                with tempfile.NamedTemporaryFile() as f:
                    dm.getFile(path, f.name)
                    self.get_gaia_info(f)
                break
        else:
            self.warn('Error pulling gaia file')

        build_props = dm.pullFile('/system/build.prop')
        desired_props = {
            'ro.build.version.incremental':
            'device_firmware_version_incremental',
            'ro.build.version.release': 'device_firmware_version_release',
            'ro.build.date.utc': 'device_firmware_date',
            'ro.product.device': 'device_id'
        }
        for line in build_props.split('\n'):
            if not line.strip().startswith('#') and '=' in line:
                key, value = [s.strip() for s in line.split('=', 1)]
                if key in desired_props.keys():
                    self._info[desired_props[key]] = value

        if self._info['device_id'].lower() == 'flame':
            self._info['device_firmware_version_base'] = dm._runCmd(
                ['shell', 'getprop', 't2m.sw.version']).output[0]
 def __init__(self, work_dir):
     self.device = mozdevice.DeviceManagerADB()
     self.work_dir = work_dir
     try:
         self.device.rmDir(work_dir)
     except:
         pass
     self.device.mkDir(work_dir)
Esempio n. 4
0
def cli():
    global webapi_results
    global webapi_results_embed_app

    parser = argparse.ArgumentParser()
    parser.add_argument("--version",
                        help="version of FxOS under test",
                        default="1.3",
                        action="store")
    parser.add_argument("--debug",
                        help="enable debug logging",
                        action="store_true")
    parser.add_argument("--list-test-groups",
                        help="print test groups available to run",
                        action="store_true")
    parser.add_argument("--include",
                        metavar="TEST-GROUP",
                        help="include this test group",
                        action="append")
    parser.add_argument("--result-file",
                        help="absolute file path to store the resulting json." \
                             "Defaults to results.json on your current path",
                        action="store")
    parser.add_argument("--generate-reference",
                        help="Generate expected result files",
                        action="store_true")
    commandline.add_logging_group(parser)

    args = parser.parse_args()

    test_groups = [
        'omni-analyzer',
        'permissions',
        'webapi',
        ]
    if args.list_test_groups:
        for t in test_groups:
            print t
        return 0

    test_groups = set(args.include if args.include else test_groups)
    report = {'buildprops': {}}

    logging.basicConfig()
    if not args.debug:
        logging.disable(logging.ERROR)

    logger = commandline.setup_logging("certsuite", vars(args), {})

    # Step 1: Get device information
    try:
        dm = mozdevice.DeviceManagerADB()
    except mozdevice.DMError, e:
        print "Error connecting to device via adb (error: %s). Please be " \
            "sure device is connected and 'remote debugging' is enabled." % \
            e.msg
        logger.error("Error connecting to device: %s" % e.msg)
        sys.exit(1)
Esempio n. 5
0
def check_adb():
    try:
        logger.info("Testing ADB connection")
        mozdevice.DeviceManagerADB()
    except mozdevice.DMError, e:
        logger.critical('Error connecting to device via adb (error: %s). Please be ' \
                        'sure device is connected and "remote debugging" is enabled.' % \
                        e.msg)
        sys.exit(1)
Esempio n. 6
0
 def unplug_and_instruct(self, message):
     self.instruct(
         "Unplug the phone.\n%s\nPlug the phone back in after you are "
         "done, and unlock the screen if necessary.\n" % message)
     dm = mozdevice.DeviceManagerADB()
     dm.forward("tcp:2828", "tcp:2828")
     self.marionette = Marionette()
     self.marionette.start_session()
     self.use_cert_app()
Esempio n. 7
0
 def getomni(self):
     # Get the omni.ja from /system/b2g/omni.ja
     # Unzip it
     try:
         dm = mozdevice.DeviceManagerADB()
     except mozdevice.DMError, e:
         print "Error connecting to device via adb (error: %s). Please be " \
             "sure device is connected and 'remote debugging' is enabled." % \
             e.msg
         sys.exit(1)
Esempio n. 8
0
    def __init__(self, marionette, datazilla_config=None, sources=None):
        self.marionette = marionette

        settings = gaiatest.GaiaData(self.marionette).all_settings  # get all settings
        mac_address = self.marionette.execute_script('return navigator.mozWifiManager && navigator.mozWifiManager.macAddress;')

        self.submit_report = True
        self.ancillary_data = {}

        if gaiatest.GaiaDevice(self.marionette).is_android_build:
            # get gaia, gecko and build revisions
            try:
                device_manager = mozdevice.DeviceManagerADB()
                app_zip = device_manager.pullFile('/data/local/webapps/settings.gaiamobile.org/application.zip')
                with zipfile.ZipFile(StringIO(app_zip)).open('resources/gaia_commit.txt') as f:
                    self.ancillary_data['gaia_revision'] = f.read().splitlines()[0]
            except zipfile.BadZipfile:
                # the zip file will not exist if Gaia has not been flashed to
                # the device, so we fall back to the sources file
                pass

            try:
                sources_xml = sources and xml.dom.minidom.parse(sources) or xml.dom.minidom.parseString(device_manager.catFile('system/sources.xml'))
                for element in sources_xml.getElementsByTagName('project'):
                    path = element.getAttribute('path')
                    revision = element.getAttribute('revision')
                    if not self.ancillary_data.get('gaia_revision') and path in 'gaia':
                        self.ancillary_data['gaia_revision'] = revision
                    if path in ['gecko', 'build']:
                        self.ancillary_data['_'.join([path, 'revision'])] = revision
            except:
                pass

        self.required = {
            'gaia revision': self.ancillary_data.get('gaia_revision'),
            'gecko revision': self.ancillary_data.get('gecko_revision'),
            'build revision': self.ancillary_data.get('build_revision'),
            'protocol': datazilla_config['protocol'],
            'host': datazilla_config['host'],
            'project': datazilla_config['project'],
            'branch': datazilla_config['branch'],
            'oauth key': datazilla_config['oauth_key'],
            'oauth secret': datazilla_config['oauth_secret'],
            'machine name': mac_address or 'unknown',
            'device name': datazilla_config['device_name'],
            'os version': settings.get('deviceinfo.os'),
            'id': settings.get('deviceinfo.platform_build_id')}

        for key, value in self.required.items():
            if not value:
                self.submit_report = False
                print '\nMissing required DataZilla field: %s' % key

        if not self.submit_report:
            print '\n***Reports will not be submitted to DataZilla***'
Esempio n. 9
0
    def __init__(self, *args, **kwargs):
        ExecutorBrowser.__init__(self, *args, **kwargs)

        import sys, subprocess

        self.dm = mozdevice.DeviceManagerADB()
        self.dm.forward("tcp:%s" % self.marionette_port, "tcp:2828")
        self.executor = None
        self.marionette = None
        self.gaia_device = None
        self.gaia_apps = None
Esempio n. 10
0
def launch_app(app_name,
               adb_path="adb",
               script_timeout=5000,
               marionette=None,
               device_serial=None):
    """
    Launches the given app
    NOTE: if a marionette session is passed, this function switches to the top-most frame.
    """
    dm = mozdevice.DeviceManagerADB(adbPath=adb_path,
                                    deviceSerial=device_serial)
    installed_app_name = app_name.lower()
    installed_app_name = installed_app_name.replace(" ", "-")
    dm.forward("tcp:2828", "tcp:2828")

    if not marionette:
        m = Marionette()
        m.start_session()
    else:
        m = marionette
        m.switch_to_frame()
    launch_app = """
    var launchWithName = function(name) {
        let apps = window.wrappedJSObject.applications || window.wrappedJSObject.Applications;
        let installedApps = apps.installedApps;
        for (let manifestURL in installedApps) {
          let app = installedApps[manifestURL];
          let origin = null;
          let entryPoints = app.manifest.entry_points;
          if (entryPoints) {
            for (let ep in entryPoints) {
              let currentEntryPoint = entryPoints[ep];
              let appName = currentEntryPoint.name;
              if (name == appName.toLowerCase()) {
                app.launch();
                return true;
              }
            }
          } else {
            let appName = app.manifest.name;
            if (name == appName.toLowerCase()) {
              app.launch();
              return true;
            }
          }
        }
        return false;
      };
    return launchWithName("%s");
    """
    m.set_script_timeout(script_timeout)
    m.execute_script(launch_app % app_name.lower())
    if not marionette:
        m.delete_session()
Esempio n. 11
0
def get_dm(marionette=None, **kwargs):
    dm_type = os.environ.get('DM_TRANS', 'adb')
    if marionette and marionette.emulator:
        adb_path = marionette.emulator.b2g.adb_path
        return mozdevice.DeviceManagerADB(adbPath=adb_path,
                                          deviceSerial='emulator-%d' %
                                          marionette.emulator.port,
                                          **kwargs)
    elif marionette and marionette.device_serial and dm_type == 'adb':
        return mozdevice.DeviceManagerADB(
            deviceSerial=marionette.device_serial, **kwargs)
    else:
        if dm_type == 'adb':
            return mozdevice.DeviceManagerADB(**kwargs)
        elif dm_type == 'sut':
            host = os.environ.get('TEST_DEVICE')
            if not host:
                raise Exception('Must specify host with SUT!')
            return mozdevice.DeviceManagerSUT(host=host)
        else:
            raise Exception('Unknown device manager type: %s' % dm_type)
Esempio n. 12
0
    def __init__(self, *args, **kwargs):
        super(TestCase, self).__init__(*args, **kwargs)
        self.stored.handler = None
        self.stored.marionette = None

        self.marionette, self.server, self.handler, self.app = None, None, None, None

        device = mozdevice.DeviceManagerADB()
        device.forward("tcp:2828", "tcp:2828")

        # Cleanups are run irrespective of whether setUp fails
        self.addCleanup(self.cleanup)
Esempio n. 13
0
 def close_app_manually(self):
     success = self.instruct(
         "Could not close %s automatically. "
         "Please close the app manually by holding down the Home button "
         "and pressing the X above the %s card." %
         (certapp.name, certapp.name))
     if not success:
         device = mozdevice.DeviceManagerADB()
         device.reboot(wait=True)
         self.instruct(
             "Please unlock the lockscreen (if present) after device reboots"
         )
         self.fail("Failed attempts at closing certapp")
Esempio n. 14
0
 def getomni(self, workdir):
     # Get the omni.ja from /system/b2g/omni.ja
     # Unzip it
     try:
         dm = mozdevice.DeviceManagerADB()
     except mozdevice.DMError as e:
         print(
             "Error connecting to device via adb (error: %s). Please be sure device is connected and 'remote debugging' is enabled."
             % e.msg)
         sys.exit(1)
     omnifile = os.path.join(workdir, 'omni.ja')
     dm.getFile(self.omni_ja_on_device, omnifile)
     unzip_omnifile(omnifile, os.path.join(workdir, 'device'))
Esempio n. 15
0
 def get_device_manager(self, *args, **kwargs):
     if not self._device_manager:
         dm_type = os.environ.get('DM_TRANS', 'adb')
         if dm_type == 'adb':
             self._device_manager = mozdevice.DeviceManagerADB(**kwargs)
         elif dm_type == 'sut':
             host = os.environ.get('TEST_DEVICE')
             if not host:
                 raise Exception('Must specify host with SUT!')
             self._device_manager = mozdevice.DeviceManagerSUT(host=host)
         else:
             raise Exception('Unknown device manager type: %s' % dm_type)
     return self._device_manager
Esempio n. 16
0
    def __init__(self, logger, prefs_root, no_backup=False):
        Browser.__init__(self, logger)
        logger.info("Waiting for device")
        subprocess.call(["adb", "wait-for-device"])
        self.device = mozdevice.DeviceManagerADB()
        self.marionette_port = get_free_port(2828, exclude=self.used_ports)
        self.used_ports.add(self.marionette_port)
        self.cert_test_app = None
        self.runner = None
        self.prefs_root = prefs_root

        self.no_backup = no_backup
        self.backup_path = None
        self.backup_paths = []
        self.backup_dirs = []
Esempio n. 17
0
 def device_manager(self):
     if not self.is_android_build:
         raise Exception('Device manager is only available for devices.')
     if hasattr(self, '_device_manager') and self._device_manager:
         return self._device_manager
     else:
         dm_type = os.environ.get('DM_TRANS', 'adb')
         if dm_type == 'adb':
             self._device_manager = mozdevice.DeviceManagerADB()
         elif dm_type == 'sut':
             host = os.environ.get('TEST_DEVICE')
             if not host:
                 raise Exception('Must specify host with SUT!')
             self._device_manager = mozdevice.DeviceManagerSUT(host=host)
         else:
             raise Exception('Unknown device manager type: %s' % dm_type)
         return self._device_manager
Esempio n. 18
0
def install_app(app_name,
                app_path,
                adb_path="adb",
                script_timeout=5000,
                marionette=None,
                device_serial=None):
    """
    This installs the given application.

    NOTE: if a marionette session is passed, this function switches to
    'content' context and will be at the top-most frame.
    """
    if is_installed(app_name, adb_path=adb_path, device_serial=device_serial):
        raise Exception("%s is already installed" % app_name)
        sys.exit(1)

    app_zip = os.path.basename(app_path)
    dm = mozdevice.DeviceManagerADB(adbPath=adb_path,
                                    deviceSerial=device_serial)
    dm.pushFile("%s" % app_path, "/data/local/%s" % app_zip)
    # forward the marionette port
    dm.forward("tcp:2828", "tcp:2828")

    # install the app
    install_js = pkg_resources.resource_filename(
        __name__, os.path.sep.join(['app_install.js']))
    with open(install_js, "r") as f:
        script = f.read()
    installed_app_name = app_name.lower().replace(" ", "-")
    script = script.replace("YOURAPPID", installed_app_name)
    script = script.replace("YOURAPPZIP", app_zip)

    if not marionette:
        m = Marionette()
        m.start_session()
    else:
        m = marionette
        m.switch_to_frame()
    m.set_context("chrome")
    m.set_script_timeout(script_timeout)
    m.execute_async_script(script)
    if not marionette:
        m.delete_session()
    else:
        m.set_context("content")
    def setup(self):
        if not self.serial or not self.port:
            logger.error("Fail to get device")
            raise DMError
        self.config_raptor()

        self.marionette and self.marionette.session and self.marionette.cleanup(
        )
        self.dm = mozdevice.DeviceManagerADB(deviceSerial=self.serial,
                                             port=self.port)
        self.marionette = Marionette(device_serial=self.serial, port=self.port)
        self.marionette.wait_for_port()
        self.marionette.start_session()
        self.device = GaiaDevice(marionette=self.marionette, manager=self.dm)
        self.apps = GaiaApps(self.marionette)
        self.data_layer = GaiaData(self.marionette)
        if self.flashed:
            self.device.wait_for_b2g_ready()
Esempio n. 20
0
 def __init__(self, dimensions, swipe_padding, input_device, orng_path):
     self.dimensions = dimensions
     self.swipe_padding = swipe_padding
     self.dm = mozdevice.DeviceManagerADB()
     self.input_device = input_device
     self.orng_path = orng_path
Esempio n. 21
0
    # Setup B2G and Firefox preferences
    pref = mozprofile.Preferences()
    pref.add(pref.read_prefs(args.prefs))
    profile = mozprofile.Profile(preferences=pref())  # Bug 908793

    # Setup Marionette
    marionette = marionette.Marionette(
        emulator='arm',
        homedir=args.b2g_dir,
        symbols_path=args.symbols_path,
        gecko_path=None,
        #logcat_dir=args.logcat_dir
    )

    # Setup DeviceManager for ADB
    device = mozdevice.DeviceManagerADB(loglevel=10)

    # Setup B2G with profile and marionette over ADB
    runner = mozrunner.B2GRunner(profile,
                                 device,
                                 marionette,
                                 context_chrome=False)
    runner.start()

    # Setup Gaia
    marionette.switch_to_frame()
    time.sleep(5)
    lock = gaiatest.LockScreen(marionette)
    lock.unlock()

    # Setup Firefox
 def __init__(self, work_dir):
     self.device = mozdevice.DeviceManagerADB()
     self.work_dir = work_dir
     self.device.mkDir(work_dir)
Esempio n. 23
0
def is_installed(app_name, adb_path="adb", device_serial=None):
    """Check if given `app_name` is installed on the attached device."""
    dm = mozdevice.DeviceManagerADB(adbPath=adb_path, deviceSerial=device_serial)
    installed_app_name = app_name.lower().replace(" ", "-")
    return dm.dirExists("/data/local/webapps/%s" % installed_app_name)
Esempio n. 24
0
 def __init__(self):
     self.device = mozdevice.DeviceManagerADB()
     self.backup_dirs = ["/data/local", "/data/b2g/mozilla"]
     self.backup_files = ["/system/etc/hosts"]
Esempio n. 25
0
def is_installed():
    device = mozdevice.DeviceManagerADB()
    return device.dirExists("/data/local/webapps/%s" % canonical_name)
Esempio n. 26
0
    def __init__(self,
                 marionette,
                 datazilla_config=None,
                 sources=None,
                 log_level='INFO',
                 device_serial=None):
        # Set up logging
        handler = mozlog.StreamHandler()
        handler.setFormatter(mozlog.MozFormatter(include_timestamp=True))
        self.logger = mozlog.getLogger(self.__class__.__name__, handler)
        self.logger.setLevel(getattr(mozlog, log_level.upper()))

        self.device_serial = device_serial
        self.marionette = marionette

        settings = gaiatest.GaiaData(self.marionette).all_settings
        mac_address = self.marionette.execute_script(
            'return navigator.mozWifiManager && '
            'navigator.mozWifiManager.macAddress;')

        self.submit_report = True
        self.ancillary_data = {
            'generated_by': 'b2gperf %s' % __version__,
            'build_url': datazilla_config['build_url']
        }

        dm = mozdevice.DeviceManagerADB(deviceSerial=self.device_serial)
        self.device = gaiatest.GaiaDevice(self.marionette, manager=dm)

        version = mozversion.get_version(sources=sources,
                                         dm_type='adb',
                                         device_serial=self.device_serial)
        self.ancillary_data['build_revision'] = version.get('build_changeset')
        self.ancillary_data['gaia_revision'] = version.get('gaia_changeset')
        self.ancillary_data['gecko_repository'] = version.get(
            'application_repository')
        self.ancillary_data['gecko_revision'] = version.get(
            'application_changeset')
        self.ancillary_data['ro.build.version.incremental'] = version.get(
            'device_firmware_version_incremental')
        self.ancillary_data['ro.build.version.release'] = version.get(
            'device_firmware_version_release')
        self.ancillary_data['ro.build.date.utc'] = version.get(
            'device_firmware_date')

        self.required = {
            'generated_by': self.ancillary_data.get('generated_by'),
            'gaia_revision': self.ancillary_data.get('gaia_revision'),
            'gecko_repository': self.ancillary_data.get('gecko_repository'),
            'gecko_revision': self.ancillary_data.get('gecko_revision'),
            'build_revision': self.ancillary_data.get('build_revision'),
            'protocol': datazilla_config['protocol'],
            'host': datazilla_config['host'],
            'project': datazilla_config['project'],
            'branch': datazilla_config['branch'],
            'oauth_key': datazilla_config['oauth_key'],
            'oauth_secret': datazilla_config['oauth_secret'],
            'machine_name': datazilla_config['machine_name'] or mac_address,
            'device_name': datazilla_config['device_name'],
            'os_version': settings.get('deviceinfo.os'),
            'id': settings.get('deviceinfo.platform_build_id')
        }

        for key, value in self.required.items():
            if value:
                self.logger.debug('DataZilla field: %s (%s)' % (key, value))
            if not value:
                self.submit_report = False
                self.logger.warn('Missing required DataZilla field: %s' % key)

        for key, value in self.ancillary_data.items():
            if value and key not in self.required.keys():
                self.logger.debug('Ancillary field: %s (%s)' % (key, value))

        if not self.submit_report:
            self.logger.info('Reports will not be submitted to DataZilla')
Esempio n. 27
0
    def __init__(self,
                 sources=None,
                 dm_type='adb',
                 host=None,
                 device_serial=None,
                 adb_host=None,
                 adb_port=None,
                 **kwargs):
        B2GVersion.__init__(self, sources, **kwargs)

        try:
            import mozdevice
        except ImportError:
            self._logger.critical("mozdevice is required to get the version"
                                  " of a remote device")
            raise

        if dm_type == 'adb':
            dm = mozdevice.DeviceManagerADB(deviceSerial=device_serial,
                                            serverHost=adb_host,
                                            serverPort=adb_port)
        elif dm_type == 'sut':
            if not host:
                raise errors.RemoteAppNotFoundError(
                    'A host for SUT must be supplied.')
            dm = mozdevice.DeviceManagerSUT(host=host)
        else:
            raise errors.RemoteAppNotFoundError(
                'Unknown device manager type: %s' % dm_type)

        if not sources:
            path = 'system/sources.xml'
            if dm.fileExists(path):
                sources = StringIO(dm.pullFile(path))
            else:
                self._logger.info('Unable to find %s' % path)

        tempdir = tempfile.mkdtemp()
        for ini in ('application', 'platform'):
            with open(os.path.join(tempdir, '%s.ini' % ini), 'w') as f:
                f.write(dm.pullFile('/system/b2g/%s.ini' % ini))
                f.flush()
        self.get_goanna_info(tempdir)
        mozfile.remove(tempdir)

        for path in ['/system/b2g', '/data/local']:
            path += '/webapps/settings.gaiamobile.org/application.zip'
            if dm.fileExists(path):
                with tempfile.NamedTemporaryFile() as f:
                    dm.getFile(path, f.name)
                    self.get_gaia_info(f)
                break
        else:
            self._logger.warning('Error pulling gaia file')

        build_props = dm.pullFile('/system/build.prop')
        desired_props = {
            'ro.build.version.incremental':
            'device_firmware_version_incremental',
            'ro.build.version.release': 'device_firmware_version_release',
            'ro.build.date.utc': 'device_firmware_date',
            'ro.product.device': 'device_id'
        }
        for line in build_props.split('\n'):
            if not line.strip().startswith('#') and '=' in line:
                key, value = [s.strip() for s in line.split('=', 1)]
                if key in desired_props.keys():
                    self._info[desired_props[key]] = value

        if self._info.get('device_id', '').lower() == 'flame':
            for prop in ['ro.boot.bootloader', 't2m.sw.version']:
                value = dm.shellCheckOutput(['getprop', prop])
                if value:
                    self._info['device_firmware_version_base'] = value
                    break
Esempio n. 28
0
def uninstall_app(app_name, adb_path="adb", script_timeout=5000, marionette=None, device_serial=None):
    """
    Uninstalls the given app.

    NOTE: if a marionette session is passed, this function switches to the top-most frame.
    """

    def check_uninstall(marionette):
        uninstall = marionette.execute_script("return window.wrappedJSObject.uninstall;")
        return uninstall != 'none'

    def check_click_uninstall(marionette):
        button = marionette.find_element('css selector', 'gaia-confirm .confirm')
        try:
            button.click()
            not_displayed = not button.is_displayed()
        except StaleElementException:
            not_displayed = True
        return not_displayed

    dm = mozdevice.DeviceManagerADB(adbPath=adb_path, deviceSerial=device_serial)
    installed_app_name = app_name.lower()
    installed_app_name = installed_app_name.replace(" ", "-")
    dm.forward("tcp:2828", "tcp:2828")

    print 'requesting uninstall of app', app_name
    if not marionette:
        m = Marionette()
        m.start_session()
    else:
        m = marionette
        m.switch_to_frame()

    m.set_context("chrome")
    m.execute_script("""
    Components.utils.import("resource://gre/modules/Services.jsm");
    window.wrappedJSObject.uninstall = 'none';
    Services.obs.addObserver(function observer(subject, topic) {
        Services.obs.removeObserver(observer, topic);
        window.wrappedJSObject.uninstall = 'ask';
        }, "webapps-ask-uninstall", false);
    Services.obs.addObserver(function observer(subject, topic) {
        Services.obs.removeObserver(observer, topic);
        window.wrappedJSObject.uninstall = 'uninstall';
        }, "webapps-uninstall", false);
        """)
    m.set_context("content")

    uninstall_app = """
    var uninstallWithName = function(name) {
        let apps = window.wrappedJSObject.applications || window.wrappedJSObject.Applications;
        let installedApps = apps.installedApps;
        for (let manifestURL in installedApps) {
          let app = installedApps[manifestURL];
          let origin = null;
          let entryPoints = app.manifest.entry_points;
          if (entryPoints) {
            for (let ep in entryPoints) {
              let currentEntryPoint = entryPoints[ep];
              let appName = currentEntryPoint.name;
              if (name == appName.toLowerCase()) {
                window.wrappedJSObject.navigator.mozApps.mgmt.uninstall(app);
                return true;
              }
            }
          } else {
            let appName = app.manifest.name;
            if (name == appName.toLowerCase()) {
              window.wrappedJSObject.navigator.mozApps.mgmt.uninstall(app);
              return true;
            }
          }
        }
        return false;
      };
    return uninstallWithName("%s");
    """
    m.set_script_timeout(script_timeout)
    result = m.execute_script(uninstall_app % app_name.lower())

    if result:
        m.set_context("chrome")
        Wait(m, 10).until(check_uninstall)
        uninstall = m.execute_script("return window.wrappedJSObject.uninstall;")
        m.set_context("content")
        if uninstall == 'ask':
            m.switch_to_frame()
            Wait(m, 20).until(element_displayed(m.find_element('css selector', 'gaia-confirm .confirm')))
            Wait(m, 20).until(check_click_uninstall)

    if not marionette:
        m.delete_session()