Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 from collections import Mapping | 5 from collections import Mapping |
| 6 import posixpath | 6 import posixpath |
| 7 | 7 |
| 8 from api_schema_graph import APISchemaGraph | 8 from api_schema_graph import APISchemaGraph |
| 9 from branch_utility import BranchUtility | 9 from branch_utility import BranchUtility, ChannelInfo |
| 10 from extensions_paths import API_PATHS, JSON_TEMPLATES | 10 from extensions_paths import API_PATHS, JSON_TEMPLATES |
| 11 from features_bundle import FeaturesBundle | 11 from features_bundle import FeaturesBundle |
| 12 import features_utility | 12 import features_utility |
| 13 from file_system import FileNotFoundError | 13 from file_system import FileNotFoundError |
| 14 from third_party.json_schema_compiler.memoize import memoize | 14 from third_party.json_schema_compiler.memoize import memoize |
| 15 from third_party.json_schema_compiler.model import UnixName | 15 from third_party.json_schema_compiler.model import UnixName |
| 16 | 16 |
| 17 | 17 |
| 18 _EXTENSION_API = 'extension_api.json' | 18 _EXTENSION_API = 'extension_api.json' |
| 19 | 19 |
| 20 # The version where api_features.json is first available. | 20 # The version where api_features.json is first available. |
| 21 _API_FEATURES_MIN_VERSION = 28 | 21 _API_FEATURES_MIN_VERSION = 28 |
| 22 # The version where permission_ and manifest_features.json are available and | 22 # The version where permission_ and manifest_features.json are available and |
| 23 # presented in the current format. | 23 # presented in the current format. |
| 24 _ORIGINAL_FEATURES_MIN_VERSION = 20 | 24 _ORIGINAL_FEATURES_MIN_VERSION = 20 |
| 25 # API schemas are aggregated in extension_api.json up to this version. | 25 # API schemas are aggregated in extension_api.json up to this version. |
| 26 _EXTENSION_API_MAX_VERSION = 17 | 26 _EXTENSION_API_MAX_VERSION = 17 |
| 27 # The earliest version for which we have SVN data. | 27 # The earliest version for which we have SVN data. |
| 28 _SVN_MIN_VERSION = 5 | 28 _SVN_MIN_VERSION = 5 |
| 29 | 29 |
| 30 | 30 |
| 31 def _GetChannelFromFeatures(api_name, features): | 31 def _GetChannelFromFeatures(api_name, features): |
| 32 '''Finds API channel information for |api_name| from |features|. | 32 '''Finds API channel information for |api_name| from |features|. |
| 33 Returns None if channel information for the API cannot be located. | 33 Returns None if channel information for the API cannot be located. |
| 34 ''' | 34 ''' |
| 35 feature = features.Get().get(api_name) | 35 feature = features.Get().get(api_name) |
| 36 return feature.get('channel') if feature else None | 36 return feature.get('channel') if feature else None |
| 37 | 37 |
| 38 | 38 |
| 39 class AvailabilityInfo(object): | |
| 40 '''Represents availability data for an API. |scheduled| is a version number | |
| 41 specifying when dev and beta APIs will become stable, or None if that data | |
| 42 is unknown. | |
| 43 ''' | |
| 44 def __init__(self, channel_info, scheduled=None): | |
| 45 assert isinstance(channel_info, ChannelInfo) | |
| 46 assert isinstance(scheduled, int) or scheduled is None | |
| 47 self.channel_info = channel_info | |
| 48 self.scheduled = scheduled | |
| 49 | |
| 50 def __eq__(self, other): | |
| 51 return self.__dict__ == other.__dict__ | |
| 52 | |
| 53 def __ne__(self, other): | |
| 54 return not (self == other) | |
| 55 | |
| 56 def __repr__(self): | |
| 57 return '%s%s' % (type(self).__name__, repr(self.__dict__)) | |
| 58 | |
| 59 def __str__(self): | |
| 60 return repr(self) | |
| 61 | |
| 62 | |
| 39 class AvailabilityFinder(object): | 63 class AvailabilityFinder(object): |
| 40 '''Generates availability information for APIs by looking at API schemas and | 64 '''Generates availability information for APIs by looking at API schemas and |
| 41 _features files over multiple release versions of Chrome. | 65 _features files over multiple release versions of Chrome. |
| 42 ''' | 66 ''' |
| 43 | 67 |
| 44 def __init__(self, | 68 def __init__(self, |
| 45 branch_utility, | 69 branch_utility, |
| 46 compiled_fs_factory, | 70 compiled_fs_factory, |
| 47 file_system_iterator, | 71 file_system_iterator, |
| 48 host_file_system, | 72 host_file_system, |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 60 | 84 |
| 61 def _GetPredeterminedAvailability(self, api_name): | 85 def _GetPredeterminedAvailability(self, api_name): |
| 62 '''Checks a configuration file for hardcoded (i.e. predetermined) | 86 '''Checks a configuration file for hardcoded (i.e. predetermined) |
| 63 availability information for an API. | 87 availability information for an API. |
| 64 ''' | 88 ''' |
| 65 api_info = self._json_fs.GetFromFile( | 89 api_info = self._json_fs.GetFromFile( |
| 66 JSON_TEMPLATES + 'api_availabilities.json').Get().get(api_name) | 90 JSON_TEMPLATES + 'api_availabilities.json').Get().get(api_name) |
| 67 if api_info is None: | 91 if api_info is None: |
| 68 return None | 92 return None |
| 69 if api_info['channel'] == 'stable': | 93 if api_info['channel'] == 'stable': |
| 70 return self._branch_utility.GetStableChannelInfo(api_info['version']) | 94 return AvailabilityInfo( |
| 95 self._branch_utility.GetStableChannelInfo(api_info['version']), | |
| 96 api_info.get('scheduled')) | |
|
not at google - send to devlin
2014/04/29 00:19:43
make explicit args explicit; "scheduled=api_info.g
danielj41
2014/04/30 21:07:11
Done.
| |
| 71 else: | 97 else: |
| 72 return self._branch_utility.GetChannelInfo(api_info['channel']) | 98 return AvailabilityInfo( |
| 99 self._branch_utility.GetChannelInfo(api_info['channel']), | |
| 100 api_info.get('scheduled')) | |
|
not at google - send to devlin
2014/04/29 00:19:43
ditto
danielj41
2014/04/30 21:07:11
Done.
| |
| 73 | 101 |
| 74 def _GetApiSchemaFilename(self, api_name, file_system, version): | 102 def _GetApiSchemaFilename(self, api_name, file_system, version): |
| 75 '''Gets the name of the file which may contain the schema for |api_name| in | 103 '''Gets the name of the file which may contain the schema for |api_name| in |
| 76 |file_system|, or None if the API is not found. Note that this may be the | 104 |file_system|, or None if the API is not found. Note that this may be the |
| 77 single _EXTENSION_API file which all APIs share in older versions of Chrome, | 105 single _EXTENSION_API file which all APIs share in older versions of Chrome, |
| 78 in which case it is unknown whether the API actually exists there. | 106 in which case it is unknown whether the API actually exists there. |
| 79 ''' | 107 ''' |
| 80 if version == 'trunk' or version > _ORIGINAL_FEATURES_MIN_VERSION: | 108 if version == 'trunk' or version > _ORIGINAL_FEATURES_MIN_VERSION: |
| 81 # API schema filenames switch format to unix_hacker_style. | 109 # API schema filenames switch format to unix_hacker_style. |
| 82 api_name = UnixName(api_name) | 110 api_name = UnixName(api_name) |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 determined to be 'stable' at the given version. | 229 determined to be 'stable' at the given version. |
| 202 ''' | 230 ''' |
| 203 if channel_info.channel == 'stable': | 231 if channel_info.channel == 'stable': |
| 204 return self._CheckStableAvailability(api_name, | 232 return self._CheckStableAvailability(api_name, |
| 205 file_system, | 233 file_system, |
| 206 channel_info.version) | 234 channel_info.version) |
| 207 return self._CheckChannelAvailability(api_name, | 235 return self._CheckChannelAvailability(api_name, |
| 208 file_system, | 236 file_system, |
| 209 channel_info) | 237 channel_info) |
| 210 | 238 |
| 239 def _FindScheduled(self, api_name): | |
| 240 '''Determines the earliest version of Chrome where the API is stable. | |
| 241 Unlike the code in GetApiAvailability, this checks if the API is stable | |
| 242 even when Chrome is in dev or beta, which shows that the API is scheduled | |
| 243 to be stable in that verison of Chrome. | |
| 244 ''' | |
| 245 def check_scheduled(file_system, channel_info): | |
| 246 return self._CheckStableAvailability( | |
| 247 api_name, file_system, channel_info.version) | |
| 248 | |
| 249 stable_channel = self._file_system_iterator.Descending( | |
| 250 self._branch_utility.GetChannelInfo('dev'), check_scheduled) | |
| 251 | |
| 252 return stable_channel.version if stable_channel else None | |
| 253 | |
| 211 def GetApiAvailability(self, api_name): | 254 def GetApiAvailability(self, api_name): |
| 212 '''Performs a search for an API's top-level availability by using a | 255 '''Performs a search for an API's top-level availability by using a |
| 213 HostFileSystemIterator instance to traverse multiple version of the | 256 HostFileSystemIterator instance to traverse multiple version of the |
| 214 SVN filesystem. | 257 SVN filesystem. |
| 215 ''' | 258 ''' |
| 216 availability = self._top_level_object_store.Get(api_name).Get() | 259 availability = self._top_level_object_store.Get(api_name).Get() |
| 217 if availability is not None: | 260 if availability is not None: |
| 218 return availability | 261 return availability |
| 219 | 262 |
| 220 # Check for predetermined availability and cache this information if found. | 263 # Check for predetermined availability and cache this information if found. |
| 221 availability = self._GetPredeterminedAvailability(api_name) | 264 availability = self._GetPredeterminedAvailability(api_name) |
| 222 if availability is not None: | 265 if availability is not None: |
| 223 self._top_level_object_store.Set(api_name, availability) | 266 self._top_level_object_store.Set(api_name, availability) |
| 224 return availability | 267 return availability |
| 225 | 268 |
| 226 def check_api_availability(file_system, channel_info): | 269 def check_api_availability(file_system, channel_info): |
| 227 return self._CheckApiAvailability(api_name, file_system, channel_info) | 270 return self._CheckApiAvailability(api_name, file_system, channel_info) |
| 228 | 271 |
| 229 availability = self._file_system_iterator.Descending( | 272 channel_info = self._file_system_iterator.Descending( |
| 230 self._branch_utility.GetChannelInfo('dev'), | 273 self._branch_utility.GetChannelInfo('dev'), |
| 231 check_api_availability) | 274 check_api_availability) |
| 232 if availability is None: | 275 if channel_info is None: |
| 233 # The API wasn't available on 'dev', so it must be a 'trunk'-only API. | 276 # The API wasn't available on 'dev', so it must be a 'trunk'-only API. |
| 234 availability = self._branch_utility.GetChannelInfo('trunk') | 277 channel_info = self._branch_utility.GetChannelInfo('trunk') |
| 278 | |
| 279 # If the API is not stable, check when it will be scheduled to be stable. | |
| 280 if channel_info.channel == 'stable': | |
| 281 scheduled = None | |
| 282 else: | |
| 283 scheduled = self._FindScheduled(api_name) | |
| 284 | |
| 285 availability = AvailabilityInfo(channel_info, scheduled) | |
| 286 | |
| 235 self._top_level_object_store.Set(api_name, availability) | 287 self._top_level_object_store.Set(api_name, availability) |
| 236 return availability | 288 return availability |
| 237 | 289 |
| 238 def GetApiNodeAvailability(self, api_name): | 290 def GetApiNodeAvailability(self, api_name): |
| 239 '''Returns an APISchemaGraph annotated with each node's availability (the | 291 '''Returns an APISchemaGraph annotated with each node's availability (the |
| 240 ChannelInfo at the oldest channel it's available in). | 292 ChannelInfo at the oldest channel it's available in). |
| 241 ''' | 293 ''' |
| 242 availability_graph = self._node_level_object_store.Get(api_name).Get() | 294 availability_graph = self._node_level_object_store.Get(api_name).Get() |
| 243 if availability_graph is not None: | 295 if availability_graph is not None: |
| 244 return availability_graph | 296 return availability_graph |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 availability_graph.Update(version_graph.Subtract(availability_graph), | 329 availability_graph.Update(version_graph.Subtract(availability_graph), |
| 278 annotation=channel_info) | 330 annotation=channel_info) |
| 279 | 331 |
| 280 previous.stat = version_stat | 332 previous.stat = version_stat |
| 281 previous.graph = version_graph | 333 previous.graph = version_graph |
| 282 | 334 |
| 283 # Continue looping until there are no longer differences between this | 335 # Continue looping until there are no longer differences between this |
| 284 # version and trunk. | 336 # version and trunk. |
| 285 return version_stat != trunk_stat | 337 return version_stat != trunk_stat |
| 286 | 338 |
| 287 self._file_system_iterator.Ascending(self.GetApiAvailability(api_name), | 339 self._file_system_iterator.Ascending( |
| 288 update_availability_graph) | 340 self.GetApiAvailability(api_name).channel_info, |
| 341 update_availability_graph) | |
| 289 | 342 |
| 290 self._node_level_object_store.Set(api_name, availability_graph) | 343 self._node_level_object_store.Set(api_name, availability_graph) |
| 291 return availability_graph | 344 return availability_graph |
| OLD | NEW |