228 lines
4.9 KiB
Python
Executable File
228 lines
4.9 KiB
Python
Executable File
#!/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_15(old):
|
|
new = copy.deepcopy(old)
|
|
new["version"] = 16
|
|
new["flamegraphModalDismissed"] = False
|
|
return new
|
|
|
|
|
|
def upgrade_16(old):
|
|
new = copy.deepcopy(old)
|
|
new["version"] = 17
|
|
new["nextId"] = max(old["nextId"], old["nextNoteId"], old["nextAreaId"])
|
|
engines = old["engines"]
|
|
if len(engines) > 0:
|
|
new["currentEngineId"] = list(engines.values())[0]['id']
|
|
return new
|
|
|
|
|
|
def upgrade_17(old):
|
|
new = copy.deepcopy(old)
|
|
new["version"] = 18
|
|
# TODO(hjd): Update
|
|
return new
|
|
|
|
|
|
def upgrade_18(old):
|
|
new = copy.deepcopy(old)
|
|
new["version"] = 19
|
|
# TODO(hjd): Update
|
|
return new
|
|
|
|
|
|
def upgrade_19(old):
|
|
new = copy.deepcopy(old)
|
|
new["version"] = 20
|
|
# TODO(hjd): Update
|
|
return new
|
|
|
|
|
|
def upgrade_20(old):
|
|
new = copy.deepcopy(old)
|
|
new["version"] = 21
|
|
# TODO(hjd): Update
|
|
return new
|
|
|
|
|
|
def upgrade_20(old):
|
|
new = copy.deepcopy(old)
|
|
new["version"] = 22
|
|
# TODO(hjd): Update
|
|
return new
|
|
|
|
|
|
def upgrade_21(old):
|
|
new = copy.deepcopy(old)
|
|
new["version"] = 22
|
|
# TODO(hjd): Update
|
|
return new
|
|
|
|
|
|
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)
|
|
parser.add_argument(
|
|
"--verbose", help=f"Show debug information", action="store_true")
|
|
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
|
|
|
|
print(json.dumps(old_json, sort_keys=True, indent=4))
|
|
|
|
UPGRADE = {
|
|
15: upgrade_15,
|
|
16: upgrade_16,
|
|
17: upgrade_17,
|
|
18: upgrade_18,
|
|
19: upgrade_19,
|
|
20: upgrade_20,
|
|
21: upgrade_21,
|
|
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())
|