| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2013 The Chromium Authors. All rights reserved. | 3 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Convert Android xml resources to API 14 compatible. | 7 """Convert Android xml resources to API 14 compatible. |
| 8 | 8 |
| 9 There are two reasons that we cannot just use API 17 attributes, | 9 There are two reasons that we cannot just use API 17 attributes, |
| 10 so we are generating another set of resources by this script. | 10 so we are generating another set of resources by this script. |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 | 224 |
| 225 | 225 |
| 226 def GenerateV14StyleResourcesInDir(input_dir, output_v14_dir): | 226 def GenerateV14StyleResourcesInDir(input_dir, output_v14_dir): |
| 227 """Convert style resources to API 14 compatible resources in input_dir.""" | 227 """Convert style resources to API 14 compatible resources in input_dir.""" |
| 228 for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'): | 228 for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'): |
| 229 rel_filename = os.path.relpath(input_filename, input_dir) | 229 rel_filename = os.path.relpath(input_filename, input_dir) |
| 230 output_v14_filename = os.path.join(output_v14_dir, rel_filename) | 230 output_v14_filename = os.path.join(output_v14_dir, rel_filename) |
| 231 GenerateV14StyleResource(input_filename, output_v14_filename) | 231 GenerateV14StyleResource(input_filename, output_v14_filename) |
| 232 | 232 |
| 233 | 233 |
| 234 def VerifyV14ResourcesInDir(input_dir, resource_type): | |
| 235 """Verify that the resources in input_dir is compatible with v14, i.e., they | |
| 236 don't use attributes that cause crashes on certain devices. Print an error if | |
| 237 they have.""" | |
| 238 for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'): | |
| 239 exception_message = ('error : ' + input_filename + ' has an RTL attribute, ' | |
| 240 'i.e., attribute that has "start" or "end" in its name.' | |
| 241 ' Pre-v17 resources should not include it because it ' | |
| 242 'can cause crashes on certain devices. Please refer to ' | |
| 243 'http://crbug.com/243952 for the details.') | |
| 244 dom = ParseAndReportErrors(input_filename) | |
| 245 if resource_type in ('layout', 'xml'): | |
| 246 if GenerateV14LayoutResourceDom(dom, input_filename, False): | |
| 247 raise Exception(exception_message) | |
| 248 elif resource_type == 'values': | |
| 249 if GenerateV14StyleResourceDom(dom, input_filename, False): | |
| 250 raise Exception(exception_message) | |
| 251 | |
| 252 | |
| 253 def AssertNoDeprecatedAttributesInDir(input_dir, resource_type): | |
| 254 """Raises an exception if resources in input_dir have deprecated attributes, | |
| 255 e.g., paddingLeft, paddingRight""" | |
| 256 for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'): | |
| 257 dom = ParseAndReportErrors(input_filename) | |
| 258 if resource_type in ('layout', 'xml'): | |
| 259 GenerateV14LayoutResourceDom(dom, input_filename) | |
| 260 elif resource_type == 'values': | |
| 261 GenerateV14StyleResourceDom(dom, input_filename) | |
| 262 | |
| 263 | |
| 264 def ParseArgs(): | 234 def ParseArgs(): |
| 265 """Parses command line options. | 235 """Parses command line options. |
| 266 | 236 |
| 267 Returns: | 237 Returns: |
| 268 An options object as from optparse.OptionsParser.parse_args() | 238 An options object as from optparse.OptionsParser.parse_args() |
| 269 """ | 239 """ |
| 270 parser = optparse.OptionParser() | 240 parser = optparse.OptionParser() |
| 271 parser.add_option('--res-dir', | 241 parser.add_option('--res-dir', |
| 272 help='directory containing resources ' | 242 help='directory containing resources ' |
| 273 'used to generate v14 compatible resources') | 243 'used to generate v14 compatible resources') |
| 274 parser.add_option('--res-v14-compatibility-dir', | 244 parser.add_option('--res-v14-compatibility-dir', |
| 275 help='output directory into which ' | 245 help='output directory into which ' |
| 276 'v14 compatible resources will be generated') | 246 'v14 compatible resources will be generated') |
| 277 parser.add_option('--stamp', help='File to touch on success') | 247 parser.add_option('--stamp', help='File to touch on success') |
| 278 parser.add_option('--verify-only', action="store_true", help='Do not generate' | |
| 279 ' v14 resources. Instead, just verify that the resources are already ' | |
| 280 "compatible with v14, i.e. they don't use attributes that cause crashes " | |
| 281 'on certain devices.') | |
| 282 | 248 |
| 283 options, args = parser.parse_args() | 249 options, args = parser.parse_args() |
| 284 | 250 |
| 285 if args: | 251 if args: |
| 286 parser.error('No positional arguments should be given.') | 252 parser.error('No positional arguments should be given.') |
| 287 | 253 |
| 288 # Check that required options have been provided. | 254 # Check that required options have been provided. |
| 289 required_options = ('res_dir', 'res_v14_compatibility_dir') | 255 required_options = ('res_dir', 'res_v14_compatibility_dir') |
| 290 build_utils.CheckOptions(options, parser, required=required_options) | 256 build_utils.CheckOptions(options, parser, required=required_options) |
| 291 return options | 257 return options |
| 292 | 258 |
| 293 def GenerateV14Resources(res_dir, res_v14_dir, verify_only): | 259 def GenerateV14Resources(res_dir, res_v14_dir): |
| 294 for name in os.listdir(res_dir): | 260 for name in os.listdir(res_dir): |
| 295 if not os.path.isdir(os.path.join(res_dir, name)): | 261 if not os.path.isdir(os.path.join(res_dir, name)): |
| 296 continue | 262 continue |
| 297 | 263 |
| 298 dir_pieces = name.split('-') | 264 dir_pieces = name.split('-') |
| 299 resource_type = dir_pieces[0] | 265 resource_type = dir_pieces[0] |
| 300 qualifiers = dir_pieces[1:] | 266 qualifiers = dir_pieces[1:] |
| 301 | 267 |
| 302 api_level_qualifier_index = -1 | 268 api_level_qualifier_index = -1 |
| 303 api_level_qualifier = '' | 269 api_level_qualifier = '' |
| 304 for index, qualifier in enumerate(qualifiers): | 270 for index, qualifier in enumerate(qualifiers): |
| 305 if re.match('v[0-9]+$', qualifier): | 271 if re.match('v[0-9]+$', qualifier): |
| 306 api_level_qualifier_index = index | 272 api_level_qualifier_index = index |
| 307 api_level_qualifier = qualifier | 273 api_level_qualifier = qualifier |
| 308 break | 274 break |
| 309 | 275 |
| 310 # Android pre-v17 API doesn't support RTL. Skip. | 276 # Android pre-v17 API doesn't support RTL. Skip. |
| 311 if 'ldrtl' in qualifiers: | 277 if 'ldrtl' in qualifiers: |
| 312 continue | 278 continue |
| 313 | 279 |
| 314 input_dir = os.path.abspath(os.path.join(res_dir, name)) | 280 input_dir = os.path.abspath(os.path.join(res_dir, name)) |
| 315 | 281 |
| 316 if verify_only: | 282 # We also need to copy the original v17 resource to *-v17 directory |
| 317 if not api_level_qualifier or int(api_level_qualifier[1:]) < 17: | 283 # because the generated v14 resource will hide the original resource. |
| 318 VerifyV14ResourcesInDir(input_dir, resource_type) | 284 output_v14_dir = os.path.join(res_v14_dir, name) |
| 319 else: | 285 output_v17_dir = os.path.join(res_v14_dir, name + '-v17') |
| 320 AssertNoDeprecatedAttributesInDir(input_dir, resource_type) | |
| 321 else: | |
| 322 # We also need to copy the original v17 resource to *-v17 directory | |
| 323 # because the generated v14 resource will hide the original resource. | |
| 324 output_v14_dir = os.path.join(res_v14_dir, name) | |
| 325 output_v17_dir = os.path.join(res_v14_dir, name + '-v17') | |
| 326 | 286 |
| 327 # We only convert layout resources under layout*/, xml*/, | 287 # We only convert layout resources under layout*/, xml*/, |
| 328 # and style resources under values*/. | 288 # and style resources under values*/. |
| 329 if resource_type in ('layout', 'xml'): | 289 if resource_type in ('layout', 'xml'): |
| 330 if not api_level_qualifier: | 290 if not api_level_qualifier: |
| 331 GenerateV14LayoutResourcesInDir(input_dir, output_v14_dir, | 291 GenerateV14LayoutResourcesInDir(input_dir, output_v14_dir, |
| 332 output_v17_dir) | 292 output_v17_dir) |
| 333 elif resource_type == 'values': | 293 elif resource_type == 'values': |
| 334 if api_level_qualifier == 'v17': | 294 if api_level_qualifier == 'v17': |
| 335 output_qualifiers = qualifiers[:] | 295 output_qualifiers = qualifiers[:] |
| 336 del output_qualifiers[api_level_qualifier_index] | 296 del output_qualifiers[api_level_qualifier_index] |
| 337 output_v14_dir = os.path.join(res_v14_dir, | 297 output_v14_dir = os.path.join(res_v14_dir, |
| 338 '-'.join([resource_type] + | 298 '-'.join([resource_type] + |
| 339 output_qualifiers)) | 299 output_qualifiers)) |
| 340 GenerateV14StyleResourcesInDir(input_dir, output_v14_dir) | 300 GenerateV14StyleResourcesInDir(input_dir, output_v14_dir) |
| 341 elif not api_level_qualifier: | 301 elif not api_level_qualifier: |
| 342 ErrorIfStyleResourceExistsInDir(input_dir) | 302 ErrorIfStyleResourceExistsInDir(input_dir) |
| 343 | 303 |
| 344 def main(): | 304 def main(): |
| 345 options = ParseArgs() | 305 options = ParseArgs() |
| 346 | 306 |
| 347 res_v14_dir = options.res_v14_compatibility_dir | 307 res_v14_dir = options.res_v14_compatibility_dir |
| 348 | 308 |
| 349 build_utils.DeleteDirectory(res_v14_dir) | 309 build_utils.DeleteDirectory(res_v14_dir) |
| 350 build_utils.MakeDirectory(res_v14_dir) | 310 build_utils.MakeDirectory(res_v14_dir) |
| 351 | 311 |
| 352 GenerateV14Resources(options.res_dir, res_v14_dir, options.verify_only) | 312 GenerateV14Resources(options.res_dir, res_v14_dir) |
| 353 | 313 |
| 354 if options.stamp: | 314 if options.stamp: |
| 355 build_utils.Touch(options.stamp) | 315 build_utils.Touch(options.stamp) |
| 356 | 316 |
| 357 if __name__ == '__main__': | 317 if __name__ == '__main__': |
| 358 sys.exit(main()) | 318 sys.exit(main()) |
| 359 | 319 |
| OLD | NEW |