1# Copyright 2016 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5 6# pylint: disable=W0201 7 8 9from recipe_engine import recipe_api 10 11from . import android 12from . import chromebook 13from . import default 14from . import docker 15from . import ios 16from . import valgrind 17 18 19"""Abstractions for running code on various platforms. 20 21The methods in this module define how certain high-level functions should work. 22Each flavor should correspond to a subclass of DefaultFlavor which may override 23any of these functions as appropriate for that flavor. 24 25For example, the AndroidFlavor will override the functions for copying files 26between the host and Android device, as well as the 'step' function, so that 27commands may be run through ADB. 28""" 29 30 31VERSION_FILE_LOTTIE = 'LOTTIE_VERSION' 32VERSION_FILE_SK_IMAGE = 'SK_IMAGE_VERSION' 33VERSION_FILE_SKP = 'SKP_VERSION' 34VERSION_FILE_SVG = 'SVG_VERSION' 35VERSION_FILE_MSKP = 'MSKP_VERSION' 36VERSION_FILE_TEXTTRACES = 'TEXTTRACES_VERSION' 37 38VERSION_NONE = -1 39 40def is_android(vars_api): 41 return ('Android' in vars_api.extra_tokens or 42 'Android' in vars_api.builder_cfg.get('os', '')) 43 44def is_chromebook(vars_api): 45 return ('Chromebook' in vars_api.extra_tokens or 46 'ChromeOS' in vars_api.builder_cfg.get('os', '')) 47 48def is_docker(vars_api): 49 return 'Docker' in vars_api.extra_tokens 50 51def is_ios(vars_api): 52 return ('iOS' in vars_api.extra_tokens or 53 'iOS' == vars_api.builder_cfg.get('os', '')) 54 55def is_valgrind(vars_api): 56 return 'Valgrind' in vars_api.extra_tokens 57 58 59class SkiaFlavorApi(recipe_api.RecipeApi): 60 def get_flavor(self, vars_api, app_name): 61 """Return a flavor utils object specific to the given builder.""" 62 if is_chromebook(vars_api): 63 return chromebook.ChromebookFlavor(self, app_name) 64 if is_android(vars_api): 65 return android.AndroidFlavor(self, app_name) 66 elif is_docker(vars_api): 67 return docker.DockerFlavor(self, app_name) 68 elif is_ios(vars_api): 69 return ios.iOSFlavor(self, app_name) 70 elif is_valgrind(vars_api): 71 return valgrind.ValgrindFlavor(self, app_name) 72 else: 73 return default.DefaultFlavor(self, app_name) 74 75 def setup(self, app_name): 76 self._f = self.get_flavor(self.m.vars, app_name) 77 self.device_dirs = self._f.device_dirs 78 self.host_dirs = self._f.host_dirs 79 self._skia_dir = self.m.path['start_dir'].join('skia') 80 81 def step(self, name, cmd, **kwargs): 82 return self._f.step(name, cmd, **kwargs) 83 84 def device_path_join(self, *args): 85 return self._f.device_path_join(*args) 86 87 def copy_directory_contents_to_device(self, host_dir, device_dir): 88 return self._f.copy_directory_contents_to_device(host_dir, device_dir) 89 90 def copy_directory_contents_to_host(self, device_dir, host_dir): 91 return self._f.copy_directory_contents_to_host(device_dir, host_dir) 92 93 def copy_file_to_device(self, host_path, device_path): 94 return self._f.copy_file_to_device(host_path, device_path) 95 96 def create_clean_host_dir(self, path): 97 return self._f.create_clean_host_dir(path) 98 99 def create_clean_device_dir(self, path): 100 return self._f.create_clean_device_dir(path) 101 102 def read_file_on_device(self, path, **kwargs): 103 return self._f.read_file_on_device(path, **kwargs) 104 105 def remove_file_on_device(self, path): 106 return self._f.remove_file_on_device(path) 107 108 def install(self, skps=False, images=False, lotties=False, svgs=False, 109 resources=False, mskps=False, texttraces=False): 110 self._f.install() 111 112 if texttraces: 113 self._copy_texttraces() 114 # TODO(borenet): Only copy files which have changed. 115 if resources: 116 self.copy_directory_contents_to_device( 117 self.m.path['start_dir'].join('skia', 'resources'), 118 self.device_dirs.resource_dir) 119 120 if skps: 121 self._copy_skps() 122 if images: 123 self._copy_images() 124 if lotties: 125 self._copy_lotties() 126 if svgs: 127 self._copy_svgs() 128 if mskps: 129 self._copy_mskps() 130 131 def cleanup_steps(self): 132 return self._f.cleanup_steps() 133 134 def _copy_dir(self, host_version, version_file, tmp_dir, 135 host_path, device_path): 136 actual_version_file = self.m.path.join(tmp_dir, version_file) 137 # Copy to device. 138 device_version_file = self.device_path_join( 139 self.device_dirs.tmp_dir, version_file) 140 if str(actual_version_file) != str(device_version_file): 141 device_version = self.read_file_on_device(device_version_file, 142 abort_on_failure=False, 143 fail_build_on_failure=False) 144 if not device_version: 145 device_version = VERSION_NONE 146 if device_version != host_version: 147 self.remove_file_on_device(device_version_file) 148 self.create_clean_device_dir(device_path) 149 self.copy_directory_contents_to_device( 150 host_path, device_path) 151 152 # Copy the new version file. 153 self.copy_file_to_device(actual_version_file, device_version_file) 154 155 def _copy_images(self): 156 """Copy test images if needed.""" 157 version = self.m.run.asset_version('skimage', self._skia_dir) 158 self.m.run.writefile( 159 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_SK_IMAGE), 160 version) 161 self._copy_dir( 162 version, 163 VERSION_FILE_SK_IMAGE, 164 self.m.vars.tmp_dir, 165 self.host_dirs.images_dir, 166 self.device_dirs.images_dir) 167 return version 168 169 def _copy_lotties(self): 170 """Copy test lotties if needed.""" 171 version = self.m.run.asset_version('lottie-samples', self._skia_dir) 172 self.m.run.writefile( 173 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_LOTTIE), 174 version) 175 self._copy_dir( 176 version, 177 VERSION_FILE_LOTTIE, 178 self.m.vars.tmp_dir, 179 self.host_dirs.lotties_dir, 180 self.device_dirs.lotties_dir) 181 return version 182 183 def _copy_skps(self): 184 """Copy the SKPs if needed.""" 185 version = self.m.run.asset_version('skp', self._skia_dir) 186 self.m.run.writefile( 187 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_SKP), 188 version) 189 self._copy_dir( 190 version, 191 VERSION_FILE_SKP, 192 self.m.vars.tmp_dir, 193 self.host_dirs.skp_dir, 194 self.device_dirs.skp_dir) 195 return version 196 197 def _copy_svgs(self): 198 """Copy the SVGs if needed.""" 199 version = self.m.run.asset_version('svg', self._skia_dir) 200 self.m.run.writefile( 201 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_SVG), 202 version) 203 self._copy_dir( 204 version, 205 VERSION_FILE_SVG, 206 self.m.vars.tmp_dir, 207 self.host_dirs.svg_dir, 208 self.device_dirs.svg_dir) 209 return version 210 211 def _copy_mskps(self): 212 """Copy the MSKPs if needed.""" 213 version = self.m.run.asset_version('mskp', self._skia_dir) 214 self.m.run.writefile( 215 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_MSKP), 216 version) 217 self._copy_dir( 218 version, 219 VERSION_FILE_MSKP, 220 self.m.vars.tmp_dir, 221 self.host_dirs.mskp_dir, 222 self.device_dirs.mskp_dir) 223 return version 224 225 def _copy_texttraces(self): 226 """Copy the text traces if needed.""" 227 version = self.m.run.asset_version('text_blob_traces', self._skia_dir) 228 self.m.run.writefile( 229 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_TEXTTRACES), 230 version) 231 self._copy_dir( 232 version, 233 VERSION_FILE_TEXTTRACES, 234 self.m.vars.tmp_dir, 235 self.host_dirs.texttraces_dir, 236 self.device_dirs.texttraces_dir) 237 return version 238