Skip to content

Commit

Permalink
feat: Conditional webkit patching based on URL with regex #127
Browse files Browse the repository at this point in the history
  • Loading branch information
shdwmtr committed Nov 30, 2024
1 parent fd6fe44 commit bf36bd5
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 124 deletions.
9 changes: 6 additions & 3 deletions assets/core/api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from api.css_analyzer import ColorTypes, convert_from_hex, convert_to_hex, parse_root
from api.themes import Colors, is_valid
from api.watchdog import SteamUtils
from util.webkit_handler import WebkitStack, add_browser_css, add_browser_js
from util.webkit_handler import WebkitStack, add_browser_css, add_browser_js, add_conditional_data, parse_conditional_patches
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

Expand Down Expand Up @@ -140,13 +140,16 @@ def start_webkit_hook(self, theme, name):
return

keys = ["Steam-WebKit", "webkitCSS", "RootColors"]
theme_path = os.path.join(Millennium.steam_path(), "steamui", "skins", name)

for key in keys:
if key in theme["data"] and isinstance(theme["data"][key], str):
add_browser_css(os.path.join(Millennium.steam_path(), "steamui", "skins", name, theme["data"][key]))
add_browser_css(os.path.join(theme_path, theme["data"][key]))

if "webkitJS" in theme["data"] and isinstance(theme["data"]["webkitJS"], str):
add_browser_js(os.path.join(Millennium.steam_path(), "steamui", "skins", name, theme["data"]["webkitJS"]))
add_browser_js(os.path.join(theme_path, theme["data"]["webkitJS"]))

add_conditional_data(theme_path, theme["data"])


def setup_colors(self, file_path):
Expand Down
8 changes: 0 additions & 8 deletions assets/core/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,6 @@
from updater.version_control import Updater
updater = Updater()

def inject_webkit_shim(shim_script: str):
# write the contents to a file
with open(os.path.join(Millennium.steam_path(), "steamui", "shim.js"), "w") as f:
f.write(shim_script)
f.close()

add_browser_js("shim.js")

def get_load_config():
millennium = configparser.ConfigParser()
config_path = os.path.join(Millennium.get_install_path(), "ext", "millennium.ini")
Expand Down
102 changes: 98 additions & 4 deletions assets/core/util/webkit_handler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# This module is intended to keep track on the webkit hooks that are added to the browser
import json
import os
import Millennium # type: ignore
from util.logger import logger

class WebkitStack:
_instance = None
Expand Down Expand Up @@ -40,10 +43,101 @@ def remove_all(self):
self.stack.clear()


def add_browser_css(css_path: str) -> None:
def parse_conditional_patches(conditional_patches: dict):
webkit_items = []

# Add condition keys into the webkit_items array
for item, condition in conditional_patches.get('Conditions', {}).items():
for value, control_flow in condition.get('values', {}).items():
# Process TargetCss
target_css = control_flow.get('TargetCss', {})
if isinstance(target_css, dict): # Ensure it's a dictionary
affects = target_css.get('affects', [])
if isinstance(affects, list): # Make sure affects is a list
for match_string in affects:
target_path = target_css.get('src')
webkit_items.append({
'matchString': match_string,
'targetPath': target_path,
'fileType': 'TargetCss'
})


# Process TargetJs
target_js = control_flow.get('TargetJs', {})
if isinstance(target_js, dict): # Ensure it's a dictionary
affects = target_js.get('affects', [])
if isinstance(affects, list): # Make sure affects is a dictionary
for match_string in affects:
target_path = target_js.get('src')
webkit_items.append({
'matchString': match_string,
'targetPath': target_path,
'fileType': 'TargetJs'
})


# Add patch keys into the webkit_items array
patches = conditional_patches.get('Patches', [])
for patch in patches: # Now we assume it's always a list
if 'TargetCss' in patch:
target_css = patch['TargetCss']
if isinstance(target_css, list):
for target in target_css:
webkit_items.append({
'matchString': patch['MatchRegexString'],
'targetPath': target,
'fileType': 'TargetCss'
})
elif isinstance(target_css, str): # Ensure it's a string if not a list
webkit_items.append({
'matchString': patch['MatchRegexString'],
'targetPath': target_css,
'fileType': 'TargetCss'
})

if 'TargetJs' in patch:
target_js = patch['TargetJs']
if isinstance(target_js, list):
for target in target_js:
webkit_items.append({
'matchString': patch['MatchRegexString'],
'targetPath': target,
'fileType': 'TargetJs'
})
elif isinstance(target_js, str): # Ensure it's a string if not a list
webkit_items.append({
'matchString': patch['MatchRegexString'],
'targetPath': target_js,
'fileType': 'TargetJs'
})

# Remove duplicates
seen = set()
unique_webkit_items = []
for item in webkit_items:
identifier = (item['matchString'], item['targetPath'])
if identifier not in seen:
seen.add(identifier)
unique_webkit_items.append(item)

return unique_webkit_items


def add_browser_css(css_path: str, regex=".*") -> None:
stack = WebkitStack()
stack.push(Millennium.add_browser_css(css_path))
stack.push(Millennium.add_browser_css(css_path, regex))

def add_browser_js(js_path: str) -> None:
def add_browser_js(js_path: str, regex=".*") -> None:
stack = WebkitStack()
stack.push(Millennium.add_browser_js(js_path))
stack.push(Millennium.add_browser_js(js_path, regex))

def add_conditional_data(path: str, data: dict):

parsed_patches = parse_conditional_patches(data)

for patch in parsed_patches:
if patch['fileType'] == 'TargetCss':
add_browser_css(os.path.join(path, patch['targetPath']), patch['matchString'])
elif patch['fileType'] == 'TargetJs':
add_browser_js(os.path.join(path, patch['targetPath']), patch['matchString'])
106 changes: 0 additions & 106 deletions assets/src/Webkit.ts

This file was deleted.

15 changes: 13 additions & 2 deletions src/api/executor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,27 @@ PyObject* RemoveBrowserModule(PyObject* self, PyObject* args)
unsigned long long AddBrowserModule(PyObject* args, WebkitHandler::TagTypes type)
{
const char* moduleItem;
const char* regexSelector = ".*"; // Default value if no second parameter is provided

if (!PyArg_ParseTuple(args, "s", &moduleItem))
// Parse arguments: moduleItem is required, regexSelector is optional
if (!PyArg_ParseTuple(args, "s|s", &moduleItem, &regexSelector))
{
return 0;
}

g_hookedModuleId++;
auto path = SystemIO::GetSteamPath() / "steamui" / moduleItem;

WebkitHandler::get().m_hookListPtr->push_back({ path.generic_string(), type, g_hookedModuleId });
try
{
WebkitHandler::get().m_hookListPtr->push_back({ path.generic_string(), std::regex(regexSelector), type, g_hookedModuleId });
}
catch (const std::regex_error& e)
{
LOG_ERROR("Attempted to add a browser module with invalid regex: {} ({})", regexSelector, e.what());
return 0;
}

return g_hookedModuleId;
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ const void PluginLoader::InjectWebkitShims()
hookIds.push_back(g_hookedModuleId);

Logger.Log("Injecting hook for '{}' with id {}", plugin.pluginName, g_hookedModuleId);
WebkitHandler::get().m_hookListPtr->push_back({ absolutePath.generic_string(), WebkitHandler::TagTypes::JAVASCRIPT, g_hookedModuleId });
WebkitHandler::get().m_hookListPtr->push_back({ absolutePath.generic_string(), std::regex(".*"), WebkitHandler::TagTypes::JAVASCRIPT, g_hookedModuleId });
}
}
}
Expand Down

0 comments on commit bf36bd5

Please sign in to comment.