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