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 chromecast 14from . import default 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' 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_chromecast(vars_api): 45 return ('Chromecast' in vars_api.extra_tokens or 46 'Chromecast' in vars_api.builder_cfg.get('os', '')) 47 48def is_chromebook(vars_api): 49 return ('Chromebook' in vars_api.extra_tokens or 50 'ChromeOS' in vars_api.builder_cfg.get('os', '')) 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): 69 """Return a flavor utils object specific to the given builder.""" 70 if is_chromecast(vars_api): 71 return chromecast.ChromecastFlavor(self) 72 if is_chromebook(vars_api): 73 return chromebook.ChromebookFlavor(self) 74 if is_android(vars_api) and not is_test_skqp(vars_api): 75 return android.AndroidFlavor(self) 76 elif is_ios(vars_api): 77 return ios.iOSFlavor(self) 78 elif is_valgrind(vars_api): 79 return valgrind.ValgrindFlavor(self) 80 elif is_win_ssh(vars_api): 81 return win_ssh.WinSSHFlavor(self) 82 else: 83 return default.DefaultFlavor(self) 84 85 def setup(self): 86 self._f = self.get_flavor(self.m.vars) 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): 120 self._f.install() 121 122 # TODO(borenet): Only copy files which have changed. 123 if resources: 124 self.copy_directory_contents_to_device( 125 self.m.path['start_dir'].join('skia', 'resources'), 126 self.device_dirs.resource_dir) 127 128 if skps: 129 self._copy_skps() 130 if images: 131 self._copy_images() 132 if lotties: 133 self._copy_lotties() 134 if svgs: 135 self._copy_svgs() 136 if mskps: 137 self._copy_mskps() 138 139 def cleanup_steps(self): 140 return self._f.cleanup_steps() 141 142 def _copy_dir(self, host_version, version_file, tmp_dir, 143 host_path, device_path): 144 actual_version_file = self.m.path.join(tmp_dir, version_file) 145 # Copy to device. 146 device_version_file = self.device_path_join( 147 self.device_dirs.tmp_dir, version_file) 148 if str(actual_version_file) != str(device_version_file): 149 device_version = self.read_file_on_device(device_version_file, 150 abort_on_failure=False, 151 fail_build_on_failure=False) 152 if not device_version: 153 device_version = VERSION_NONE 154 if device_version != host_version: 155 self.remove_file_on_device(device_version_file) 156 self.create_clean_device_dir(device_path) 157 self.copy_directory_contents_to_device( 158 host_path, device_path) 159 160 # Copy the new version file. 161 self.copy_file_to_device(actual_version_file, device_version_file) 162 163 def _copy_images(self): 164 """Copy test images if needed.""" 165 version = self.m.run.asset_version('skimage', self._skia_dir) 166 self.m.run.writefile( 167 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_SK_IMAGE), 168 version) 169 self._copy_dir( 170 version, 171 VERSION_FILE_SK_IMAGE, 172 self.m.vars.tmp_dir, 173 self.host_dirs.images_dir, 174 self.device_dirs.images_dir) 175 return version 176 177 def _copy_lotties(self): 178 """Copy test lotties if needed.""" 179 version = self.m.run.asset_version('lottie-samples', self._skia_dir) 180 self.m.run.writefile( 181 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_LOTTIE), 182 version) 183 self._copy_dir( 184 version, 185 VERSION_FILE_LOTTIE, 186 self.m.vars.tmp_dir, 187 self.host_dirs.lotties_dir, 188 self.device_dirs.lotties_dir) 189 return version 190 191 def _copy_skps(self): 192 """Copy the SKPs if needed.""" 193 version = self.m.run.asset_version('skp', self._skia_dir) 194 self.m.run.writefile( 195 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_SKP), 196 version) 197 self._copy_dir( 198 version, 199 VERSION_FILE_SKP, 200 self.m.vars.tmp_dir, 201 self.host_dirs.skp_dir, 202 self.device_dirs.skp_dir) 203 return version 204 205 def _copy_svgs(self): 206 """Copy the SVGs if needed.""" 207 version = self.m.run.asset_version('svg', self._skia_dir) 208 self.m.run.writefile( 209 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_SVG), 210 version) 211 self._copy_dir( 212 version, 213 VERSION_FILE_SVG, 214 self.m.vars.tmp_dir, 215 self.host_dirs.svg_dir, 216 self.device_dirs.svg_dir) 217 return version 218 219 def _copy_mskps(self): 220 """Copy the MSKPs if needed.""" 221 version = self.m.run.asset_version('mskp', self._skia_dir) 222 self.m.run.writefile( 223 self.m.path.join(self.m.vars.tmp_dir, VERSION_FILE_MSKP), 224 version) 225 self._copy_dir( 226 version, 227 VERSION_FILE_MSKP, 228 self.m.vars.tmp_dir, 229 self.host_dirs.mskp_dir, 230 self.device_dirs.mskp_dir) 231 return version 232