11# -*- coding: utf-8 -*-
22"""Check Chrome OS recovery images availability"""
33
4- from xml .etree import ElementTree as ET
54import requests
65from lib .inputstreamhelper .config import CHROMEOS_RECOVERY_ARM_BNAMES , CHROMEOS_RECOVERY_ARM64_BNAMES , CHROMEOS_RECOVERY_URL
76
@@ -14,37 +13,57 @@ def __init__(self, message):
1413 super (OutdatedException , self ).__init__ (self .message )
1514
1615
17- def get_devices ():
18- """Get Chrome OS devices as json object"""
19- url = 'https://www.chromium.org/chromium-os/developer-library/reference/development/developer-information-for-chrome-os-devices/'
20- response = requests .get (url , timeout = 10 )
21- response .raise_for_status ()
22- html = response .text .split ('<table>' )[- 1 ].split ('</table>' )[0 ]
23- html = '<table>' + html + '</table>'
24- html = html .replace ('&' , '&' )
25- html = html .replace ('<white label>' , 'white label' )
26- table = ET .XML (html .encode ('utf-8' ))
27- keys = [k .text .strip () for k in table [0 ]]
28- devices = []
29- for row in table [1 :]:
30- device = {}
31- for num , value in enumerate (row ):
32- device [keys [num ]] = None
33- if value .text :
34- device [keys [num ]] = value .text .strip ()
35- elif value .find ('a' ) is not None and value .find ('a' ).text is not None :
36- device [keys [num ]] = value .find ('a' ).text .strip ()
37- devices .append (device )
38- return devices
39-
40-
4116def get_arm_devices ():
4217 """Get Chrome OS ARM devices as json object"""
43- devices = get_devices ()
18+ serves = get_serves ()
4419 arm_devices = []
45- for device in devices :
46- if device .get ('User ABI' ).lower () in ('arm' , 'aarch64' ):
47- arm_devices .append (device )
20+
21+ for main , data in serves .items ():
22+ # Collect all candidate boards (top-level + submodels)
23+ candidates = []
24+
25+ # Top-level board
26+ if 'brandNameToFormattedDeviceMap' in data :
27+ candidates .append ((data .get ('fsiMilestoneNumber' , 0 ), data , main .split ('-' )[- 1 ]))
28+
29+ # Submodels
30+ for sub_data in (data .get ('models' ) or {}).values ():
31+ if 'brandNameToFormattedDeviceMap' in sub_data :
32+ candidates .append ((sub_data .get ('fsiMilestoneNumber' , 0 ), sub_data , main ))
33+
34+ if not candidates :
35+ continue
36+
37+ # Pick the board with the highest milestone number
38+ _ , best , board = max (candidates , key = lambda x : x [0 ] or 0 )
39+
40+ device_map = best .get ('brandNameToFormattedDeviceMap' , {})
41+ push_recoveries = best .get ('pushRecoveries' , {})
42+ max_version = int (max (push_recoveries .keys (), default = 0 ))
43+ first_available = best .get ('fsiMilestoneNumber' )
44+ eol = best .get ('isAue' , False )
45+
46+ serving_stable = best .get ('servingStable' , {})
47+ chrome_version = serving_stable .get ('chromeVersion' )
48+ version = serving_stable .get ('version' )
49+
50+ # Build output entries for ARM devices
51+ entry = {
52+ board : {
53+ 'first' : first_available ,
54+ 'last' : max_version ,
55+ 'eol' : eol ,
56+ 'chrome' : chrome_version ,
57+ 'version' : version ,
58+ }
59+ }
60+
61+ # Append only if architecture is ARM
62+ for info in device_map .values ():
63+ arch = info .get ('architecture' , '' ).lower ()
64+ if arch in {'arm_64' , 'arm_32' } and entry not in arm_devices :
65+ arm_devices .append (entry )
66+
4867 return arm_devices
4968
5069
@@ -68,13 +87,11 @@ def get_recoveries():
6887def get_compatibles ():
6988 """Get compatible Chrome OS recovery items"""
7089 arm_devices = get_arm_devices ()
71- serves = get_serves ()
7290 recoveries = get_recoveries ()
7391 compatibles = []
7492 for device in arm_devices :
75- board = device .get ('Board name(s)' ).lower ().replace ('_' , '-' )
76- served_board = serves .get (board )
77- if served_board and not served_board .get ('isAue' ):
93+ board = next (iter (device ), None )
94+ if board and not device [board ].get ('eol' ):
7895 for recovery in recoveries :
7996 r_board = recovery .get ('file' ).split ('_' )[2 ]
8097 if board == r_board :
0 commit comments