class B2GPopulate(object): PERSISTENT_STORAGE_PATH = '/data/local/storage/persistent' handler = mozlog.StreamHandler() handler.setFormatter(mozlog.MozFormatter(include_timestamp=True)) logger = mozlog.getLogger('B2GPopulate', handler) def __init__(self, marionette, log_level='INFO'): self.marionette = marionette self.data_layer = GaiaData(self.marionette) self.device = GaiaDevice(self.marionette) dm = mozdevice.DeviceManagerADB() self.device.add_device_manager(dm) self.logger.setLevel(getattr(mozlog, log_level.upper())) if self.device.is_android_build: self.idb_dir = 'idb' for candidate in self.device.manager.listFiles( '/'.join([self.PERSISTENT_STORAGE_PATH, 'chrome'])): if re.match('\d.*idb', candidate): self.idb_dir = candidate break def populate(self, call_count=None, contact_count=None, message_count=None, music_count=None, picture_count=None, video_count=None, event_count=None): restart = any([call_count, contact_count, message_count]) if restart: self.logger.debug('Stopping B2G') self.device.stop_b2g() if call_count is not None: self.populate_calls(call_count, restart=False) if contact_count is not None: self.populate_contacts(contact_count, restart=False) if event_count is not None: self.populate_events(event_count, restart=False) if message_count is not None: self.populate_messages(message_count, restart=False) if restart: self.start_b2g() if music_count > 0: self.populate_music(music_count) if picture_count > 0: self.populate_pictures(picture_count) if video_count > 0: self.populate_videos(video_count) def populate_calls(self, count, restart=True): # only allow preset db values for calls db_counts = DB_PRESET_COUNTS['call'] if not count in db_counts: raise InvalidCountError('call') self.logger.info('Populating %d calls' % count) db_counts.sort(reverse=True) for marker in db_counts: if count >= marker: key = 'communications.gaiamobile.org' local_id = json.loads(self.device.manager.pullFile( '/data/local/webapps/webapps.json'))[key]['localId'] db_zip_name = pkg_resources.resource_filename( __name__, os.path.sep.join(['resources', 'dialerDb.zip'])) db_name = 'dialerDb-%d.sqlite' % marker self.logger.debug('Extracting %s from %s' % ( db_name, db_zip_name)) db = ZipFile(db_zip_name).extract(db_name) if restart: self.device.stop_b2g() destination = '/'.join([self.PERSISTENT_STORAGE_PATH, '%s+f+app+++%s' % (local_id, key), self.idb_dir, '2584670174dsitanleecreR.sqlite']) self.logger.debug('Pushing %s to %s' % (db, destination)) self.device.push_file(db, destination=destination) self.logger.debug('Removing %s' % db) os.remove(db) if restart: self.start_b2g() break def populate_contacts(self, count, restart=True, include_pictures=True): # only allow preset db values for contacts db_counts = DB_PRESET_COUNTS['contact'] if not count in db_counts: raise InvalidCountError('contact') self.device.manager.removeDir('/'.join([ self.PERSISTENT_STORAGE_PATH, 'chrome', self.idb_dir, '*csotncta*'])) self.logger.info('Populating %d contacts' % count) db_counts.sort(reverse=True) for marker in db_counts: if count >= marker: db_zip_name = pkg_resources.resource_filename( __name__, os.path.sep.join(['resources', 'contactsDb.zip'])) db_name = 'contactsDb-%d.sqlite' % marker self.logger.debug('Extracting %s from %s' % ( db_name, db_zip_name)) db = ZipFile(db_zip_name).extract(db_name) if restart: self.device.stop_b2g() destination = '/'.join([ self.PERSISTENT_STORAGE_PATH, 'chrome', self.idb_dir, '3406066227csotncta.sqlite']) self.logger.debug('Pushing %s to %s' % (db, destination)) self.device.push_file(db, destination=destination) self.logger.debug('Removing %s' % db) os.remove(db) if marker > 0 and include_pictures: self.logger.debug('Adding contact pictures') pictures_zip_name = pkg_resources.resource_filename( __name__, os.path.sep.join( ['resources', 'contactsPictures.zip'])) temp = tempfile.mkdtemp() self.logger.debug('Extracting %s to %s' % ( pictures_zip_name, temp)) ZipFile(pictures_zip_name).extractall(temp) destination = '/'.join([ self.PERSISTENT_STORAGE_PATH, 'chrome', self.idb_dir, '3406066227csotncta']) self.logger.debug('Pushing %s to %s' % (temp, destination)) self.device.manager.pushDir(temp, destination) self.logger.debug('Removing %s' % temp) shutil.rmtree(temp) if restart: self.start_b2g() break def populate_events(self, count, restart=True): # only allow preset db values for events db_counts = DB_PRESET_COUNTS['event'] if not count in db_counts: raise InvalidCountError('event') self.logger.info('Populating %d events' % count) db_counts.sort(reverse=True) for marker in db_counts: if count >= marker: key = 'calendar.gaiamobile.org' local_id = json.loads(self.device.manager.pullFile( '/data/local/webapps/webapps.json'))[key]['localId'] db_zip_name = pkg_resources.resource_filename( __name__, os.path.sep.join(['resources', 'calendarDb.zip'])) db_name = 'calendarDb-%d.sqlite' % marker self.logger.debug('Extracting %s from %s' % ( db_name, db_zip_name)) db = ZipFile(db_zip_name).extract(db_name) if restart: self.device.stop_b2g() destination = '/'.join([self.PERSISTENT_STORAGE_PATH, '%s+f+app+++%s' % (local_id, key), self.idb_dir, '125582036br2agd-nceal.sqlite']) self.logger.debug('Pushing %s to %s' % (db, destination)) self.device.push_file(db, destination=destination) self.logger.debug('Removing %s' % db) os.remove(db) if restart: self.start_b2g() break def populate_messages(self, count, restart=True): # only allow preset db values for messages db_counts = DB_PRESET_COUNTS['message'] if not count in db_counts: raise InvalidCountError('message') self.logger.info('Populating %d messages' % count) db_counts.sort(reverse=True) for marker in db_counts: if count >= marker: db_zip_name = pkg_resources.resource_filename( __name__, os.path.sep.join(['resources', 'smsDb.zip'])) db_name = 'smsDb-%d.sqlite' % marker self.logger.debug('Extracting %s from %s' % ( db_name, db_zip_name)) db = ZipFile(db_zip_name).extract(db_name) if restart: self.device.stop_b2g() destination = '/'.join([ self.PERSISTENT_STORAGE_PATH, 'chrome', self.idb_dir, '226660312ssm.sqlite']) self.logger.debug('Pushing %s to %s' % (db, destination)) self.device.push_file(db, destination=destination) os.remove(db) if marker > 0: self.logger.debug('Adding message attachments') all_attachments_zip_name = pkg_resources.resource_filename( __name__, os.path.sep.join( ['resources', 'smsAttachments.zip'])) attachments_zip_name = 'smsAttachments-%d.zip' % marker self.logger.debug('Extracting %s from %s' % ( attachments_zip_name, all_attachments_zip_name)) attachments_zip = ZipFile( all_attachments_zip_name).extract(attachments_zip_name) temp = tempfile.mkdtemp() self.logger.debug('Extracting %s to %s' % ( attachments_zip, temp)) ZipFile(attachments_zip).extractall(temp) destination = '/'.join([ self.PERSISTENT_STORAGE_PATH, 'chrome', self.idb_dir, '226660312ssm']) self.logger.debug('Pushing %s to %s' % (temp, destination)) self.device.manager.pushDir(temp, destination) self.logger.debug('Removing %s' % temp) shutil.rmtree(temp) self.logger.debug('Removing %s' % attachments_zip) os.remove(attachments_zip) if restart: self.start_b2g() break def populate_music(self, count, source='MUS_0001.mp3', destination='sdcard', tracks_per_album=10): self.remove_media('music') import math from mutagen.easyid3 import EasyID3 music_file = pkg_resources.resource_filename( __name__, os.path.sep.join(['resources', source])) local_filename = music_file.rpartition(os.path.sep)[-1] # copy the mp3 file into a temp location with tempfile.NamedTemporaryFile() as local_copy: self.logger.debug('Creating copy of %s at %s' % ( music_file, local_copy.name)) local_copy.write(open(music_file).read()) music_file = local_copy.name mp3 = EasyID3(music_file) album_count = math.ceil(float(count) / tracks_per_album) self.logger.info('Populating %d music files (%d album%s)' % ( count, album_count, 's' if album_count > 1 else '')) for i in range(1, count + 1): album = math.ceil(float(i) / float(tracks_per_album)) track = i - ((album - 1) * tracks_per_album) mp3['title'] = 'Track %d' % track mp3['artist'] = 'Artist %d' % album mp3['album'] = 'Album %d' % album mp3['tracknumber'] = str(track) mp3.save() remote_filename = '_%s.'.join( iter(local_filename.split('.'))) % i remote_destination = os.path.join(destination, remote_filename) self.logger.debug('Pushing %s to %s' % ( music_file, remote_destination)) self.device.push_file(music_file, 1, remote_destination) def populate_pictures(self, count, source='IMG_0001.jpg', destination='sdcard/DCIM/100MZLLA'): self.populate_files('picture', source, count, destination) def populate_videos(self, count, source='VID_0001.3gp', destination='sdcard/DCIM/100MZLLA'): self.populate_files('video', source, count, destination) def populate_files(self, file_type, source, count, destination=''): self.remove_media(file_type) self.logger.info('Populating %d %s files' % (count, file_type)) source_file = pkg_resources.resource_filename( __name__, os.path.sep.join(['resources', source])) self.logger.debug('Pushing %d copies of %s to %s' % ( count, source_file, destination)) self.device.push_file(source_file, count, destination) def remove_media(self, file_type): if self.device.is_android_build: files = getattr(self.data_layer, '%s_files' % file_type) or [] if len(files) > 0: self.logger.info('Removing %d %s files' % ( len(files), file_type)) for filename in files: self.logger.debug('Removing %s' % filename) self.device.manager.removeFile(filename) # TODO Wait for files to be deleted time.sleep(5) files = getattr(self.data_layer, '%s_files' % file_type) or [] if not len(files) == 0: raise IncorrectCountError( '%s files' % file_type, 0, len(files)) def start_b2g(self): self.logger.debug('Starting B2G') self.device.start_b2g() self.data_layer = GaiaData(self.marionette)