mirror of
https://github.com/GAM-team/GAM.git
synced 2025-07-09 22:23:35 +00:00
Implement Chrome version history (#1354)
* Implement Chrome version history * Update GamCommands.txt * Use httpObj
This commit is contained in:
@ -1246,6 +1246,49 @@ gam print chromeversions [todrive]
|
||||
[ou|org|orgunit <OrgUnitItem>]
|
||||
[start <Date>] [end <Date>] [recentfirst]
|
||||
|
||||
<ChromePlatformType>> ::=
|
||||
all'|
|
||||
android'|
|
||||
ios'|
|
||||
lacros'|
|
||||
linux'|
|
||||
mac'|
|
||||
macarm64'|
|
||||
sebview'|
|
||||
win'|
|
||||
win64'
|
||||
<ChromeChannelType> ::=
|
||||
beta'|
|
||||
canary'|
|
||||
canaryasan'|
|
||||
dev'|
|
||||
stable'
|
||||
<ChromeVersionsOrderByFieldName> ::=
|
||||
channel|
|
||||
name|
|
||||
platform|
|
||||
version|
|
||||
<ChromeReleasesOrderByFieldName> ::=
|
||||
channel|
|
||||
endtime|
|
||||
fraction|
|
||||
name|
|
||||
platform|
|
||||
starttime|
|
||||
version
|
||||
|
||||
gam print chromehistory platforms [todrive]
|
||||
gam print chromehistory channels [todrive]
|
||||
[platform <ChromePlatformType>]
|
||||
gam print chromehistory versions [todrive]
|
||||
[platform <ChromePlatformType>] [channel <ChromeChannelType>]
|
||||
[filter <String>]
|
||||
(orderby <ChromeVersionsOrderByFieldName> [ascending|descending])*
|
||||
gam print chromehistory releases [todrive]
|
||||
[platform <ChromePlatformType>] [channel <ChromeChannelType>] [version <String>]
|
||||
[filter <String>]
|
||||
(orderby <ChromeReleasessOrderByFieldName> [ascending|descending])*
|
||||
|
||||
gam delete chromepolicy <SchemaName>+ ou|org|orgunit <OrgUnitItem> [(printerid <PrinterID>)|(appid <AppID>)]
|
||||
gam update chromepolicy (<SchemaName> (<Field> <Value>)+)+ ou|org|orgunit <OrgUnitItem> [(printerid <PrinterID>)|(appid <AppID>)]
|
||||
gam show chromepolicy ou|org|orgunit <OrgUnitItem> [(printerid <PrinterID>)|(appid <AppID>)]
|
||||
|
@ -14,6 +14,7 @@ extra_files = [(os.path.join(proot, 'cacerts.txt'), 'httplib2')]
|
||||
extra_files += copy_metadata('google-api-python-client')
|
||||
extra_files += [('cbcm-v1.1beta1.json', '.')]
|
||||
extra_files += [('contactdelegation-v1.json', '.')]
|
||||
extra_files += [('versionhistory-v1.json', '.')]
|
||||
|
||||
a = Analysis(['gam/__main__.py'],
|
||||
hiddenimports=[],
|
||||
|
@ -53,6 +53,7 @@ from gam import fileutils
|
||||
from gam.gapi import calendar as gapi_calendar
|
||||
from gam.gapi import cloudidentity as gapi_cloudidentity
|
||||
from gam.gapi import cbcm as gapi_cbcm
|
||||
from gam.gapi import chromehistory as gapi_chromehistory
|
||||
from gam.gapi import chromemanagement as gapi_chromemanagement
|
||||
from gam.gapi import chromepolicy as gapi_chromepolicy
|
||||
from gam.gapi.cloudidentity import devices as gapi_cloudidentity_devices
|
||||
@ -893,14 +894,14 @@ def getValidOauth2TxtCredentials(force_refresh=False, api=None):
|
||||
return credentials
|
||||
|
||||
|
||||
def getService(api, http):
|
||||
def getService(api, httpObj):
|
||||
api, version, api_version = getAPIVersion(api)
|
||||
if api in GM_Globals[GM_CURRENT_API_SERVICES] and version in GM_Globals[
|
||||
GM_CURRENT_API_SERVICES][api]:
|
||||
service = googleapiclient.discovery.build_from_document(
|
||||
GM_Globals[GM_CURRENT_API_SERVICES][api][version], http=http)
|
||||
GM_Globals[GM_CURRENT_API_SERVICES][api][version], http=httpObj)
|
||||
if GM_Globals[GM_CACHE_DISCOVERY_ONLY]:
|
||||
http.cache = None
|
||||
httpObj.cache = None
|
||||
return service
|
||||
if api in V1_DISCOVERY_APIS:
|
||||
discoveryServiceUrl = googleapiclient.discovery.DISCOVERY_URI
|
||||
@ -912,7 +913,7 @@ def getService(api, http):
|
||||
service = googleapiclient.discovery.build(
|
||||
api,
|
||||
version,
|
||||
http=http,
|
||||
http=httpObj,
|
||||
cache_discovery=False,
|
||||
static_discovery=False,
|
||||
discoveryServiceUrl=discoveryServiceUrl)
|
||||
@ -920,23 +921,25 @@ def getService(api, http):
|
||||
GM_Globals[GM_CURRENT_API_SERVICES][api][
|
||||
version] = service._rootDesc.copy()
|
||||
if GM_Globals[GM_CACHE_DISCOVERY_ONLY]:
|
||||
http.cache = None
|
||||
httpObj.cache = None
|
||||
return service
|
||||
except (httplib2.ServerNotFoundError, RuntimeError) as e:
|
||||
if n != retries:
|
||||
http.connections = {}
|
||||
httpObj.connections = {}
|
||||
controlflow.wait_on_failure(n, retries, str(e))
|
||||
continue
|
||||
controlflow.system_error_exit(4, str(e))
|
||||
except (googleapiclient.errors.InvalidJsonError, KeyError,
|
||||
ValueError) as e:
|
||||
http.cache = None
|
||||
httpObj.cache = None
|
||||
if n != retries:
|
||||
controlflow.wait_on_failure(n, retries, str(e))
|
||||
continue
|
||||
controlflow.system_error_exit(17, str(e))
|
||||
except (http_client.ResponseNotReady, OSError,
|
||||
googleapiclient.errors.HttpError) as e:
|
||||
if 'The request is missing a valid API key' in str(e):
|
||||
break
|
||||
if n != retries:
|
||||
controlflow.wait_on_failure(n, retries, str(e))
|
||||
continue
|
||||
@ -946,12 +949,12 @@ def getService(api, http):
|
||||
disc_file, discovery = readDiscoveryFile(api_version)
|
||||
try:
|
||||
service = googleapiclient.discovery.build_from_document(discovery,
|
||||
http=http)
|
||||
http=httpObj)
|
||||
GM_Globals[GM_CURRENT_API_SERVICES].setdefault(api, {})
|
||||
GM_Globals[GM_CURRENT_API_SERVICES][api][
|
||||
version] = service._rootDesc.copy()
|
||||
if GM_Globals[GM_CACHE_DISCOVERY_ONLY]:
|
||||
http.cache = None
|
||||
httpObj.cache = None
|
||||
return service
|
||||
except (KeyError, ValueError):
|
||||
controlflow.invalid_json_exit(disc_file)
|
||||
@ -961,9 +964,9 @@ def buildGAPIObject(api):
|
||||
GM_Globals[GM_CURRENT_API_USER] = None
|
||||
credentials = getValidOauth2TxtCredentials(api=getAPIVersion(api)[0])
|
||||
credentials.user_agent = GAM_INFO
|
||||
http = transport.AuthorizedHttp(
|
||||
httpObj = transport.AuthorizedHttp(
|
||||
credentials, transport.create_http(cache=GM_Globals[GM_CACHE_DIR]))
|
||||
service = getService(api, http)
|
||||
service = getService(api, httpObj)
|
||||
if GC_Values[GC_DOMAIN]:
|
||||
if not GC_Values[GC_CUSTOMER_ID]:
|
||||
resp, result = service._http.request(
|
||||
@ -995,6 +998,12 @@ def buildGAPIObject(api):
|
||||
return service
|
||||
|
||||
|
||||
def buildGAPIObjectNoAuthentication(api):
|
||||
GM_Globals[GM_CURRENT_API_USER] = None
|
||||
httpObj = transport.create_http(cache=GM_Globals[GM_CACHE_DIR])
|
||||
service = getService(api, httpObj)
|
||||
return service
|
||||
|
||||
# Convert UID to email address
|
||||
def convertUIDtoEmailAddress(emailAddressOrUID, cd=None, email_types=['user']):
|
||||
if isinstance(email_types, str):
|
||||
@ -1078,23 +1087,23 @@ def convertEmailAddressToUID(emailAddressOrUID, cd=None, email_type='user'):
|
||||
|
||||
|
||||
def buildGAPIServiceObject(api, act_as, showAuthError=True):
|
||||
http = transport.create_http(cache=GM_Globals[GM_CACHE_DIR])
|
||||
service = getService(api, http)
|
||||
httpObj = transport.create_http(cache=GM_Globals[GM_CACHE_DIR])
|
||||
service = getService(api, httpObj)
|
||||
GM_Globals[GM_CURRENT_API_USER] = act_as
|
||||
GM_Globals[GM_CURRENT_API_SCOPES] = API_SCOPE_MAPPING.get(
|
||||
api, service._rootDesc['auth']['oauth2']['scopes'])
|
||||
credentials = getSvcAcctCredentials(GM_Globals[GM_CURRENT_API_SCOPES],
|
||||
act_as)
|
||||
request = transport.create_request(http)
|
||||
request = transport.create_request(httpObj)
|
||||
retries = 3
|
||||
for n in range(1, retries + 1):
|
||||
try:
|
||||
credentials.refresh(request)
|
||||
service._http = transport.AuthorizedHttp(credentials, http=http)
|
||||
service._http = transport.AuthorizedHttp(credentials, http=httpObj)
|
||||
break
|
||||
except (httplib2.ServerNotFoundError, RuntimeError) as e:
|
||||
if n != retries:
|
||||
http.connections = {}
|
||||
httpObj.connections = {}
|
||||
controlflow.wait_on_failure(n, retries, str(e))
|
||||
continue
|
||||
controlflow.system_error_exit(4, e)
|
||||
@ -11533,6 +11542,8 @@ def ProcessGAMCommand(args):
|
||||
gapi_chromemanagement.printAppDevices()
|
||||
elif argument in ['chromeversions']:
|
||||
gapi_chromemanagement.printVersions()
|
||||
elif argument in ['chromehistory']:
|
||||
gapi_chromehistory.printHistory()
|
||||
else:
|
||||
controlflow.invalid_argument_exit(argument, 'gam print')
|
||||
sys.exit(0)
|
||||
|
153
src/gam/gapi/chromehistory.py
Normal file
153
src/gam/gapi/chromehistory.py
Normal file
@ -0,0 +1,153 @@
|
||||
"""Chrome Version History API calls"""
|
||||
|
||||
import sys
|
||||
|
||||
import gam
|
||||
from gam.var import *
|
||||
from gam import controlflow
|
||||
from gam import display
|
||||
from gam import gapi
|
||||
from gam import utils
|
||||
|
||||
|
||||
def build():
|
||||
return gam.buildGAPIObjectNoAuthentication('versionhistory')
|
||||
|
||||
|
||||
CHROME_HISTORY_ENTITY_CHOICES = {
|
||||
'platforms',
|
||||
'channels',
|
||||
'versions',
|
||||
'releases',
|
||||
}
|
||||
CHROME_PLATFORM_CHOICE_MAP = {
|
||||
'all': 'all',
|
||||
'android': 'android',
|
||||
'ios': 'ios',
|
||||
'lacros': 'lacros',
|
||||
'linux': 'linux',
|
||||
'mac': 'mac',
|
||||
'macarm64': 'mac_arm64',
|
||||
'sebview': 'webview',
|
||||
'win': 'win',
|
||||
'win64': 'win64',
|
||||
}
|
||||
CHROME_CHANNEL_CHOICE_MAP = {
|
||||
'beta': 'beta',
|
||||
'canary': 'canary',
|
||||
'canaryasan': 'canary_asan',
|
||||
'dev': 'dev',
|
||||
'stable': 'stable',
|
||||
}
|
||||
CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP = {
|
||||
'versions': {
|
||||
'channel': 'channel',
|
||||
'name': 'name',
|
||||
'platform': 'platform',
|
||||
'version': 'version'
|
||||
},
|
||||
'releases': {
|
||||
'channel': 'channel',
|
||||
'endtime': 'endtime',
|
||||
'fraction': 'fraction',
|
||||
'name': 'name',
|
||||
'platform': 'platform',
|
||||
'starttime': 'starttime',
|
||||
'version': 'version'
|
||||
}
|
||||
}
|
||||
CHROME_VERSIONHISTORY_TITLES = {
|
||||
'platforms': ['name', 'platformType'],
|
||||
'channels': ['name', 'channelType'],
|
||||
'versions': ['name', 'version'],
|
||||
'releases': ['name', 'version', 'fraction', 'serving.startTime', 'serving.endTime']
|
||||
}
|
||||
|
||||
def printHistory():
|
||||
cv = build()
|
||||
entityType = sys.argv[3].lower().replace('_', '')
|
||||
if entityType not in CHROME_HISTORY_ENTITY_CHOICES:
|
||||
msg = f'{entityType} is not a valid argument to "gam print chromehistory"'
|
||||
controlflow.system_error_exit(3, msg)
|
||||
todrive = False
|
||||
csvRows = []
|
||||
cplatform = 'all'
|
||||
channel = 'all'
|
||||
version = 'all'
|
||||
kwargs = {}
|
||||
orderByList = []
|
||||
i = 4
|
||||
while i < len(sys.argv):
|
||||
myarg = sys.argv[i].lower().replace('_', '')
|
||||
if myarg == 'todrive':
|
||||
todrive = True
|
||||
i += 1
|
||||
elif entityType != 'platforms' and myarg == 'platform':
|
||||
cplatform = sys.argv[i + 1].lower().replace('_', '')
|
||||
if cplatform not in CHROME_PLATFORM_CHOICE_MAP:
|
||||
controlflow.expected_argument_exit('platform',
|
||||
', '.join(CHROME_PLATFORM_CHOICE_MAP),
|
||||
cplatform)
|
||||
cplatform = CHROME_PLATFORM_CHOICE_MAP[cplatform]
|
||||
i += 2
|
||||
elif entityType in {'versions', 'releases'} and myarg == 'channel':
|
||||
channel = sys.argv[i + 1].lower().replace('_', '')
|
||||
if channel not in CHROME_CHANNEL_CHOICE_MAP:
|
||||
controlflow.expected_argument_exit('channel',
|
||||
', '.join(CHROME_CHANNEL_CHOICE_MAP),
|
||||
channel)
|
||||
channel = CHROME_CHANNEL_CHOICE_MAP[channel]
|
||||
i += 2
|
||||
elif entityType == 'releases' and myarg == 'version':
|
||||
version = sys.argv[i + 1]
|
||||
i += 2
|
||||
elif entityType in {'versions', 'releases'} and myarg == 'orderby':
|
||||
fieldName = sys.argv[i + 1].lower().replace('_', '')
|
||||
i += 2
|
||||
if fieldName in CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP[entityType]:
|
||||
fieldName = CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP[entityType][fieldName]
|
||||
orderBy = ''
|
||||
if i < len(sys.argv):
|
||||
orderBy = sys.argv[i].lower()
|
||||
if orderBy in SORTORDER_CHOICES_MAP:
|
||||
orderBy = SORTORDER_CHOICES_MAP[orderBy]
|
||||
i += 1
|
||||
if orderBy != 'DESCENDING':
|
||||
orderByList.append(fieldName)
|
||||
else:
|
||||
orderByList.append(f'{fieldName} desc')
|
||||
else:
|
||||
controlflow.expected_argument_exit('orderby',
|
||||
', '.join(CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP[entityType]),
|
||||
fieldName)
|
||||
elif entityType in {'versions', 'releases'} and myarg == 'filter':
|
||||
kwargs['filter'] = sys.argv[i + 1]
|
||||
i += 2
|
||||
else:
|
||||
msg = f'{myarg} is not a valid argument to "gam print chromehistory {entityType}"'
|
||||
controlflow.system_error_exit(3, msg)
|
||||
if orderByList:
|
||||
kwargs['orderBy'] = ','.join(orderByList)
|
||||
if entityType == 'platforms':
|
||||
svc = cv.platforms()
|
||||
parent = 'chrome'
|
||||
elif entityType == 'channels':
|
||||
svc = cv.platforms().channels()
|
||||
parent = f'chrome/platforms/{cplatform}'
|
||||
elif entityType == 'versions':
|
||||
svc = cv.platforms().channels().versions()
|
||||
parent = f'chrome/platforms/{cplatform}/channels/{channel}'
|
||||
else: #elif entityType == 'releases'
|
||||
svc = cv.platforms().channels().versions().releases()
|
||||
parent = f'chrome/platforms/{cplatform}/channels/{channel}/versions/{version}'
|
||||
reportTitle = f'Chrome Version History {entityType.capitalize()}'
|
||||
page_message = gapi.got_total_items_msg(reportTitle, '...\n')
|
||||
gam.printGettingAllItems(reportTitle, None)
|
||||
citems = gapi.get_all_pages(svc, 'list', entityType,
|
||||
page_message=page_message,
|
||||
parent=parent,
|
||||
fields=f'nextPageToken,{entityType}',
|
||||
**kwargs)
|
||||
for citem in citems:
|
||||
csvRows.append(utils.flatten_json(citem))
|
||||
display.write_csv_file(csvRows, CHROME_VERSIONHISTORY_TITLES[entityType], reportTitle, todrive)
|
@ -40,19 +40,19 @@ def create_http(cache=None,
|
||||
return httpObj
|
||||
|
||||
|
||||
def create_request(http=None):
|
||||
def create_request(httpObj=None):
|
||||
"""Creates a uniform Request object with a default http, if not provided.
|
||||
|
||||
Args:
|
||||
http: Optional httplib2.Http compatible object to be used with the request.
|
||||
httpObj: Optional httplib2.Http compatible object to be used with the request.
|
||||
If not provided, a default HTTP will be used.
|
||||
|
||||
Returns:
|
||||
Request: A google_auth_httplib2.Request compatible Request.
|
||||
"""
|
||||
if not http:
|
||||
http = create_http()
|
||||
return Request(http)
|
||||
if not httpObj:
|
||||
httpObj = create_http()
|
||||
return Request(httpObj)
|
||||
|
||||
|
||||
GAM_USER_AGENT = GAM_INFO
|
||||
|
@ -324,6 +324,7 @@ API_VER_MAPPING = {
|
||||
'siteVerification': 'v1',
|
||||
'storage': 'v1',
|
||||
'vault': 'v1',
|
||||
'versionhistory': 'v1',
|
||||
}
|
||||
|
||||
USERINFO_EMAIL_SCOPE = 'https://www.googleapis.com/auth/userinfo.email'
|
||||
|
486
src/versionhistory-v1.json
Normal file
486
src/versionhistory-v1.json
Normal file
@ -0,0 +1,486 @@
|
||||
{
|
||||
"revision": "20210322",
|
||||
"name": "versionhistory",
|
||||
"mtlsRootUrl": "https://versionhistory.mtls.googleapis.com/",
|
||||
"version_module": true,
|
||||
"basePath": "",
|
||||
"title": "Version History API",
|
||||
"kind": "discovery#restDescription",
|
||||
"servicePath": "",
|
||||
"ownerDomain": "google.com",
|
||||
"parameters": {
|
||||
"access_token": {
|
||||
"location": "query",
|
||||
"description": "OAuth access token.",
|
||||
"type": "string"
|
||||
},
|
||||
"alt": {
|
||||
"default": "json",
|
||||
"location": "query",
|
||||
"enum": [
|
||||
"json",
|
||||
"media",
|
||||
"proto"
|
||||
],
|
||||
"type": "string",
|
||||
"enumDescriptions": [
|
||||
"Responses with Content-Type of application/json",
|
||||
"Media download with context-dependent Content-Type",
|
||||
"Responses with Content-Type of application/x-protobuf"
|
||||
],
|
||||
"description": "Data format for response."
|
||||
},
|
||||
"quotaUser": {
|
||||
"type": "string",
|
||||
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
|
||||
"location": "query"
|
||||
},
|
||||
"$.xgafv": {
|
||||
"location": "query",
|
||||
"enumDescriptions": [
|
||||
"v1 error format",
|
||||
"v2 error format"
|
||||
],
|
||||
"enum": [
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"description": "V1 error format.",
|
||||
"type": "string"
|
||||
},
|
||||
"fields": {
|
||||
"type": "string",
|
||||
"description": "Selector specifying which fields to include in a partial response.",
|
||||
"location": "query"
|
||||
},
|
||||
"key": {
|
||||
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"callback": {
|
||||
"location": "query",
|
||||
"description": "JSONP",
|
||||
"type": "string"
|
||||
},
|
||||
"oauth_token": {
|
||||
"description": "OAuth 2.0 token for the current user.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"upload_protocol": {
|
||||
"location": "query",
|
||||
"type": "string",
|
||||
"description": "Upload protocol for media (e.g. \"raw\", \"multipart\")."
|
||||
},
|
||||
"prettyPrint": {
|
||||
"description": "Returns response with indentations and line breaks.",
|
||||
"default": "true",
|
||||
"location": "query",
|
||||
"type": "boolean"
|
||||
},
|
||||
"uploadType": {
|
||||
"description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
|
||||
"type": "string",
|
||||
"location": "query"
|
||||
}
|
||||
},
|
||||
"ownerName": "Google",
|
||||
"protocol": "rest",
|
||||
"resources": {
|
||||
"platforms": {
|
||||
"methods": {
|
||||
"list": {
|
||||
"httpMethod": "GET",
|
||||
"parameterOrder": [
|
||||
"parent"
|
||||
],
|
||||
"response": {
|
||||
"$ref": "ListPlatformsResponse"
|
||||
},
|
||||
"path": "v1/{+parent}/platforms",
|
||||
"description": "Returns list of platforms that are avaialble for a given product. The resource \"product\" has no resource name in its name.",
|
||||
"flatPath": "v1/{v1Id}/platforms",
|
||||
"id": "versionhistory.platforms.list",
|
||||
"parameters": {
|
||||
"parent": {
|
||||
"location": "path",
|
||||
"pattern": "^[^/]+$",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"description": "Required. The product, which owns this collection of platforms. Format: {product}"
|
||||
},
|
||||
"pageSize": {
|
||||
"format": "int32",
|
||||
"description": "Optional. Optional limit on the number of channels to include in the response. If unspecified, the server will pick an appropriate default.",
|
||||
"type": "integer",
|
||||
"location": "query"
|
||||
},
|
||||
"pageToken": {
|
||||
"location": "query",
|
||||
"description": "Optional. A page token, received from a previous `ListChannels` call. Provide this to retrieve the subsequent page.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"channels": {
|
||||
"resources": {
|
||||
"versions": {
|
||||
"resources": {
|
||||
"releases": {
|
||||
"methods": {
|
||||
"list": {
|
||||
"id": "versionhistory.platforms.channels.versions.releases.list",
|
||||
"path": "v1/{+parent}/releases",
|
||||
"httpMethod": "GET",
|
||||
"parameterOrder": [
|
||||
"parent"
|
||||
],
|
||||
"response": {
|
||||
"$ref": "ListReleasesResponse"
|
||||
},
|
||||
"flatPath": "v1/{v1Id}/platforms/{platformsId}/channels/{channelsId}/versions/{versionsId}/releases",
|
||||
"parameters": {
|
||||
"parent": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"description": "Required. The version, which owns this collection of releases. Format: {product}/platforms/{platform}/channels/{channel}/versions/{version}",
|
||||
"pattern": "^[^/]+/platforms/[^/]+/channels/[^/]+/versions/[^/]+$",
|
||||
"location": "path"
|
||||
},
|
||||
"filter": {
|
||||
"type": "string",
|
||||
"location": "query",
|
||||
"description": "Optional. Filter string. Format is a comma separated list of All comma separated filter clauses are conjoined with a logical \"and\". Valid field_names are \"version\", \"name\", \"platform\", \"channel\", \"fraction\" \"starttime\", and \"endtime\". Valid operators are \"\u003c\", \"\u003c=\", \"=\", \"\u003e=\", and \"\u003e\". Channel comparison is done by distance from stable. must be a valid channel when filtering by channel. Ex) stable \u003c beta, beta \u003c dev, canary \u003c canary_asan. Version comparison is done numerically. Ex) 1.0.0.8 \u003c 1.0.0.10. If version is not entirely written, the version will be appended with 0 for the missing fields. Ex) version \u003e 80 becoms version \u003e 80.0.0.0 When filtering by starttime or endtime, string must be in RFC 3339 date string format. Name and platform are filtered by string comparison. Ex) \"...?filter=channel\u003c=beta, version \u003e= 80 Ex) \"...?filter=version \u003e 80, version \u003c 81 Ex) \"...?filter=starttime\u003e2020-01-01T00:00:00Z"
|
||||
},
|
||||
"orderBy": {
|
||||
"location": "query",
|
||||
"description": "Optional. Ordering string. Valid order_by strings are \"version\", \"name\", \"starttime\", \"endtime\", \"platform\", \"channel\", and \"fraction\". Optionally, you can append \"desc\" or \"asc\" to specify the sorting order. Multiple order_by strings can be used in a comma separated list. Ordering by channel will sort by distance from the stable channel (not alphabetically). A list of channels sorted in this order is: stable, beta, dev, canary, and canary_asan. Sorting by name may cause unexpected behaviour as it is a naive string sort. For example, 1.0.0.8 will be before 1.0.0.10 in descending order. If order_by is not specified the response will be sorted by starttime in descending order. Ex) \"...?order_by=starttime asc\" Ex) \"...?order_by=platform desc, channel, startime desc\"",
|
||||
"type": "string"
|
||||
},
|
||||
"pageSize": {
|
||||
"location": "query",
|
||||
"format": "int32",
|
||||
"description": "Optional. Optional limit on the number of releases to include in the response. If unspecified, the server will pick an appropriate default.",
|
||||
"type": "integer"
|
||||
},
|
||||
"pageToken": {
|
||||
"description": "Optional. A page token, received from a previous `ListReleases` call. Provide this to retrieve the subsequent page.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"description": "Returns list of releases of the given version."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"methods": {
|
||||
"list": {
|
||||
"response": {
|
||||
"$ref": "ListVersionsResponse"
|
||||
},
|
||||
"path": "v1/{+parent}/versions",
|
||||
"parameters": {
|
||||
"pageSize": {
|
||||
"location": "query",
|
||||
"format": "int32",
|
||||
"description": "Optional. Optional limit on the number of versions to include in the response. If unspecified, the server will pick an appropriate default.",
|
||||
"type": "integer"
|
||||
},
|
||||
"pageToken": {
|
||||
"description": "Optional. A page token, received from a previous `ListVersions` call. Provide this to retrieve the subsequent page.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"required": true,
|
||||
"location": "path",
|
||||
"description": "Required. The channel, which owns this collection of versions. Format: {product}/platforms/{platform}/channels/{channel}",
|
||||
"pattern": "^[^/]+/platforms/[^/]+/channels/[^/]+$",
|
||||
"type": "string"
|
||||
},
|
||||
"orderBy": {
|
||||
"type": "string",
|
||||
"location": "query",
|
||||
"description": "Optional. Ordering string. Valid order_by strings are \"version\", \"name\", \"platform\", and \"channel\". Optionally, you can append \" desc\" or \" asc\" to specify the sorting order. Multiple order_by strings can be used in a comma separated list. Ordering by channel will sort by distance from the stable channel (not alphabetically). A list of channels sorted in this order is: stable, beta, dev, canary, and canary_asan. Sorting by name may cause unexpected behaviour as it is a naive string sort. For example, 1.0.0.8 will be before 1.0.0.10 in descending order. If order_by is not specified the response will be sorted by version in descending order. Ex) \"...?order_by=version asc\" Ex) \"...?order_by=platform desc, channel, version\""
|
||||
},
|
||||
"filter": {
|
||||
"description": "Optional. Filter string. Format is a comma separated list of All comma separated filter clauses are conjoined with a logical \"and\". Valid field_names are \"version\", \"name\", \"platform\", and \"channel\". Valid operators are \"\u003c\", \"\u003c=\", \"=\", \"\u003e=\", and \"\u003e\". Channel comparison is done by distance from stable. Ex) stable \u003c beta, beta \u003c dev, canary \u003c canary_asan. Version comparison is done numerically. If version is not entirely written, the version will be appended with 0 in missing fields. Ex) version \u003e 80 becoms version \u003e 80.0.0.0 Name and platform are filtered by string comparison. Ex) \"...?filter=channel\u003c=beta, version \u003e= 80 Ex) \"...?filter=version \u003e 80, version \u003c 81",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"id": "versionhistory.platforms.channels.versions.list",
|
||||
"parameterOrder": [
|
||||
"parent"
|
||||
],
|
||||
"description": "Returns list of version for the given platform/channel.",
|
||||
"flatPath": "v1/{v1Id}/platforms/{platformsId}/channels/{channelsId}/versions",
|
||||
"httpMethod": "GET"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"methods": {
|
||||
"list": {
|
||||
"response": {
|
||||
"$ref": "ListChannelsResponse"
|
||||
},
|
||||
"parameterOrder": [
|
||||
"parent"
|
||||
],
|
||||
"parameters": {
|
||||
"pageToken": {
|
||||
"type": "string",
|
||||
"location": "query",
|
||||
"description": "Optional. A page token, received from a previous `ListChannels` call. Provide this to retrieve the subsequent page."
|
||||
},
|
||||
"parent": {
|
||||
"location": "path",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"pattern": "^[^/]+/platforms/[^/]+$",
|
||||
"description": "Required. The platform, which owns this collection of channels. Format: {product}/platforms/{platform}"
|
||||
},
|
||||
"pageSize": {
|
||||
"format": "int32",
|
||||
"type": "integer",
|
||||
"description": "Optional. Optional limit on the number of channels to include in the response. If unspecified, the server will pick an appropriate default.",
|
||||
"location": "query"
|
||||
}
|
||||
},
|
||||
"path": "v1/{+parent}/channels",
|
||||
"httpMethod": "GET",
|
||||
"flatPath": "v1/{v1Id}/platforms/{platformsId}/channels",
|
||||
"id": "versionhistory.platforms.channels.list",
|
||||
"description": "Returns list of channels that are available for a given platform."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Version History API - Prod",
|
||||
"discoveryVersion": "v1",
|
||||
"schemas": {
|
||||
"Channel": {
|
||||
"id": "Channel",
|
||||
"type": "object",
|
||||
"description": "Each Channel is owned by a Platform and owns a collection of versions. Possible Channels are listed in the Channel enum below. Not all Channels are available for every Platform (e.g. CANARY does not exist for LINUX).",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Channel name. Format is \"{product}/platforms/{platform}/channels/{channel}\"",
|
||||
"type": "string"
|
||||
},
|
||||
"channelType": {
|
||||
"description": "Type of channel.",
|
||||
"enumDescriptions": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"CHANNEL_TYPE_UNSPECIFIED",
|
||||
"STABLE",
|
||||
"BETA",
|
||||
"DEV",
|
||||
"CANARY",
|
||||
"CANARY_ASAN",
|
||||
"ALL",
|
||||
"EXTENDED"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Interval": {
|
||||
"description": "Represents a time interval, encoded as a Timestamp start (inclusive) and a Timestamp end (exclusive). The start must be less than or equal to the end. When the start equals the end, the interval is empty (matches no time). When both start and end are unspecified, the interval matches any time.",
|
||||
"type": "object",
|
||||
"id": "Interval",
|
||||
"properties": {
|
||||
"endTime": {
|
||||
"type": "string",
|
||||
"format": "google-datetime",
|
||||
"description": "Optional. Exclusive end of the interval. If specified, a Timestamp matching this interval will have to be before the end."
|
||||
},
|
||||
"startTime": {
|
||||
"format": "google-datetime",
|
||||
"type": "string",
|
||||
"description": "Optional. Inclusive start of the interval. If specified, a Timestamp matching this interval will have to be the same or after the start."
|
||||
}
|
||||
}
|
||||
},
|
||||
"ListVersionsResponse": {
|
||||
"description": "Response message for ListVersions.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"versions": {
|
||||
"type": "array",
|
||||
"description": "The list of versions.",
|
||||
"items": {
|
||||
"$ref": "Version"
|
||||
}
|
||||
},
|
||||
"nextPageToken": {
|
||||
"description": "A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"id": "ListVersionsResponse"
|
||||
},
|
||||
"ListChannelsResponse": {
|
||||
"description": "Response message for ListChannels.",
|
||||
"id": "ListChannelsResponse",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nextPageToken": {
|
||||
"description": "A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages.",
|
||||
"type": "string"
|
||||
},
|
||||
"channels": {
|
||||
"description": "The list of channels.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "Channel"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Platform": {
|
||||
"properties": {
|
||||
"platformType": {
|
||||
"enum": [
|
||||
"PLATFORM_TYPE_UNSPECIFIED",
|
||||
"WIN",
|
||||
"WIN64",
|
||||
"MAC",
|
||||
"LINUX",
|
||||
"ANDROID",
|
||||
"WEBVIEW",
|
||||
"IOS",
|
||||
"ALL",
|
||||
"MAC_ARM64",
|
||||
"LACROS"
|
||||
],
|
||||
"description": "Type of platform.",
|
||||
"enumDescriptions": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Platform name. Format is \"{product}/platforms/{platform}\"",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"id": "Platform",
|
||||
"type": "object",
|
||||
"description": "Each Platform is owned by a Product and owns a collection of channels. Available platforms are listed in Platform enum below. Not all Channels are available for every Platform (e.g. CANARY does not exist for LINUX)."
|
||||
},
|
||||
"Version": {
|
||||
"properties": {
|
||||
"version": {
|
||||
"description": "String containing just the version number. e.g. \"84.0.4147.38\"",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Version name. Format is \"{product}/platforms/{platform}/channels/{channel}/versions/{version}\" e.g. \"chrome/platforms/win/channels/beta/versions/84.0.4147.38\"",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"id": "Version",
|
||||
"type": "object",
|
||||
"description": "Each Version is owned by a Channel. A Version only displays the Version number (e.g. 84.0.4147.38). A Version owns a collection of releases."
|
||||
},
|
||||
"ListPlatformsResponse": {
|
||||
"description": "Response message for ListPlatforms.",
|
||||
"id": "ListPlatformsResponse",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nextPageToken": {
|
||||
"type": "string",
|
||||
"description": "A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages."
|
||||
},
|
||||
"platforms": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "Platform"
|
||||
},
|
||||
"description": "The list of platforms."
|
||||
}
|
||||
}
|
||||
},
|
||||
"ListReleasesResponse": {
|
||||
"type": "object",
|
||||
"id": "ListReleasesResponse",
|
||||
"description": "Response message for ListReleases.",
|
||||
"properties": {
|
||||
"nextPageToken": {
|
||||
"description": "A token, which can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages.",
|
||||
"type": "string"
|
||||
},
|
||||
"releases": {
|
||||
"description": "The list of releases.",
|
||||
"items": {
|
||||
"$ref": "Release"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Release": {
|
||||
"properties": {
|
||||
"fraction": {
|
||||
"format": "double",
|
||||
"type": "number",
|
||||
"description": "Rollout fraction. This fraction indicates the fraction of people that should receive this version in this release. If the fraction is not specified in ReleaseManager, the API will assume fraction is 1."
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "String containing just the version number. e.g. \"84.0.4147.38\""
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Release name. Format is \"{product}/platforms/{platform}/channels/{channel}/versions/{version}/releases/{release}\""
|
||||
},
|
||||
"serving": {
|
||||
"description": "Timestamp interval of when the release was live. If end_time is unspecified, the release is currently live.",
|
||||
"$ref": "Interval"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"description": "A Release is owned by a Version. A Release contains information about the release(s) of its parent version. This includes when the release began and ended, as well as what percentage it was released at. If the version is released again, or if the serving percentage changes, it will create another release under the version.",
|
||||
"id": "Release"
|
||||
}
|
||||
},
|
||||
"fullyEncodeReservedExpansion": true,
|
||||
"documentationLink": "https://developers.chrome.com/",
|
||||
"icons": {
|
||||
"x16": "http://www.google.com/images/icons/product/search-16.gif",
|
||||
"x32": "http://www.google.com/images/icons/product/search-32.gif"
|
||||
},
|
||||
"baseUrl": "https://versionhistory.googleapis.com/",
|
||||
"batchPath": "batch",
|
||||
"version": "v1",
|
||||
"canonicalName": "Version History",
|
||||
"id": "versionhistory:v1",
|
||||
"rootUrl": "https://versionhistory.googleapis.com/"
|
||||
}
|
Reference in New Issue
Block a user