diff --git a/src/browsergym/workarena/__init__.py b/src/browsergym/workarena/__init__.py index 04dac6d..afeafe1 100644 --- a/src/browsergym/workarena/__init__.py +++ b/src/browsergym/workarena/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.5.2" +__version__ = "0.5.3" # Check playwright version early to avoid cryptic errors import importlib.metadata diff --git a/src/browsergym/workarena/tasks/form.py b/src/browsergym/workarena/tasks/form.py index 742dc0e..c32e83d 100644 --- a/src/browsergym/workarena/tasks/form.py +++ b/src/browsergym/workarena/tasks/form.py @@ -395,6 +395,30 @@ def get_init_scripts(self) -> List[str]: runInGsftMainOnlyAndProtectByURL(removeAdditionalActionsButton, '{url_suffix}'); """, + f""" + function removeContextMenus() {{ + waLog('Setting up context menu removal observer...', 'removeContextMenus'); + // Remove any existing context menus + document.querySelectorAll('.context_menu').forEach((menu) => {{ + menu.remove(); + }}); + // Observe for new context menus being added + const observer = new MutationObserver((mutations) => {{ + mutations.forEach((mutation) => {{ + mutation.addedNodes.forEach((node) => {{ + if (node.nodeType === 1 && node.classList && node.classList.contains('context_menu')) {{ + node.remove(); + waLog('Removed dynamically added context menu', 'removeContextMenus'); + }} + }}); + }}); + }}); + observer.observe(document.body, {{ childList: true, subtree: true }}); + waLog('Context menu observer active', 'removeContextMenus'); + }} + + runInGsftMainOnlyAndProtectByURL(removeContextMenus, '{url_suffix}'); + """, ] def start(self, page: Page) -> None: diff --git a/src/browsergym/workarena/tasks/list.py b/src/browsergym/workarena/tasks/list.py index 0f67f42..6c01418 100644 --- a/src/browsergym/workarena/tasks/list.py +++ b/src/browsergym/workarena/tasks/list.py @@ -116,6 +116,7 @@ def get_init_scripts(self) -> List[str]: return super().get_init_scripts() + [ "registerGsftMainLoaded();", self._get_remove_personalize_list_button_script(), + self._get_remove_context_menus_script(), ] def _get_remove_personalize_list_button_script(self): @@ -136,6 +137,37 @@ def _get_remove_personalize_list_button_script(self): """ return script + def _get_remove_context_menus_script(self): + """ + Removes context menus that appear on right-click in list views. + These menus provide options that could be used to modify list data outside the task scope. + """ + script = """ + function removeContextMenus() { + waLog('Setting up context menu removal observer...', 'removeContextMenus'); + // Remove any existing context menus + document.querySelectorAll('.context_menu').forEach((menu) => { + menu.remove(); + }); + // Observe for new context menus being added + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + mutation.addedNodes.forEach((node) => { + if (node.nodeType === 1 && node.classList && node.classList.contains('context_menu')) { + node.remove(); + waLog('Removed dynamically added context menu', 'removeContextMenus'); + } + }); + }); + }); + observer.observe(document.body, { childList: true, subtree: true }); + waLog('Context menu observer active', 'removeContextMenus'); + } + + runInGsftMainOnlyAndProtectByURL(removeContextMenus, '_list.do'); + """ + return script + def _get_visible_list(self, page: Page): self._wait_for_ready(page)