blob: a6e8fab71f3f84aab20e47b78bbc415b2465cef6 [file] [log] [blame]
#!/usr/bin/env python3
import sys
import argparse
import urllib
import json
import urllib.request
import urllib.parse
import ssl
import hashlib
import copy
BUCKET_NAME = "perfetto-ui-data"
CURRENT_STATE_VERSION = 28
def upgrade_22(old):
new = copy.deepcopy(old)
new["version"] = 23
new["logFilteringCriteria"] = {
"minimumLevel": 2,
}
return new
def upgrade_23(old):
new = copy.deepcopy(old)
new["version"] = 24
current_engine_id = new["currentEngineId"]
new["engine"] = new["engines"][
current_engine_id] if current_engine_id else None
del new["currentEngineId"]
del new["engines"]
return new
def upgrade_24(old):
new = copy.deepcopy(old)
new["version"] = 25
new["omniboxState"] = new["frontendLocalState"]["omniboxState"]
del new["frontendLocalState"]["omniboxState"]
return new
def upgrade_25(old):
new = copy.deepcopy(old)
new["version"] = 26
new["logFilteringCriteria"]["tags"] = []
return new
def upgrade_26(old):
new = copy.deepcopy(old)
new["version"] = 27
new["logFilteringCriteria"]["textEntry"] = ""
return new
def upgrade_27(old):
new = copy.deepcopy(old)
new["version"] = 28
new["logFilteringCriteria"]["hideNonMatching"] = False
return new
def bug_compatible_hash_mangling(hash):
pairs = [hash[i:i + 2] for i in range(0, len(hash), 2)]
return ''.join([pair.removeprefix("0") for pair in pairs])
def upload_state(state):
data = state.encode("utf-8")
hash = bug_compatible_hash_mangling(hashlib.sha256(data).hexdigest())
try:
get(make_state_url(hash))
except:
pass
else:
return hash
url = f"https://www.googleapis.com/upload/storage/v1/b/{BUCKET_NAME}/o?uploadType=media&name={hash}&predefinedAcl=publicRead"
request = urllib.request.Request(url, data=data)
request.add_header("Content-Type", "application/json; charset=utf-8")
response = urllib.request.urlopen(request)
return hash
def make_state_url(id):
return f"https://storage.googleapis.com/{BUCKET_NAME}/{id}"
def make_ui_url(id):
return f"https://ui.perfetto.dev/#!/?s={id}"
def extract_state_uuid(url):
fragment = urllib.parse.urlparse(url).fragment
fragment = fragment.removeprefix("!/?")
return urllib.parse.parse_qs(fragment)["s"][0]
def get(url):
context = ssl._create_unverified_context()
response = urllib.request.urlopen(url, context=context)
contents = response.read().decode()
return contents
def post(url):
context = ssl._create_unverified_context()
response = urllib.request.urlopen(url, context=context)
contents = response.read().decode()
return contents
def main():
parser = argparse.ArgumentParser()
parser.add_argument("permalink", help="Permalink you wish to update")
parser.add_argument(
"--target-version",
help=f"Target state version (default: {CURRENT_STATE_VERSION})",
default=CURRENT_STATE_VERSION)
args = parser.parse_args()
permalink_url = args.permalink
old_uuid = extract_state_uuid(permalink_url)
old_state_url = make_state_url(old_uuid)
old_state = get(old_state_url)
old_json = json.loads(old_state)
old_state_version = old_json["version"]
new_state_version = args.target_version
UPGRADE = {
22: upgrade_22,
23: upgrade_23,
24: upgrade_24,
25: upgrade_25,
26: upgrade_26,
27: upgrade_27,
}
new_json = old_json
for i in range(old_state_version, new_state_version):
new_json = UPGRADE[i](new_json)
new_state = json.dumps(new_json)
new_uuid = upload_state(new_state)
new_url = make_ui_url(new_uuid)
print(f"Your new permalink is accessible at:")
print(f"{new_url}")
return 0
if __name__ == "__main__":
sys.exit(main())