Chrome: browser rules stop matching in windows that have shown a New Tab Page (`chrome://newtab-footer/` WebArea is picked as the tab URL)
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 72/100
Línea de trabajo
Empieza en Utilities/Accessibility/QueryWebAreaService.swift, en fetchScrollArea(), donde la DFS devuelve el primer AXWebArea cuyo esquema no es chrome-extension. En las ventanas que ya han mostrado una NTP, el WebArea del pie de página con chrome://newtab-footer/ se extrae primero. Ejecuta el fragmento dump.swift del issue en una ventana afectada para confirmar la URL elegida. Se considera terminado cuando se omite el WebArea del pie de página (por ejemplo, excluyendo también el esquema chrome, o haciendo coincidir el WebArea cuya URL es igual a AXDocument) y una pestaña de github.com se resuelve a su propia URL en una ventana que ha mostrado la NTP.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
Current Chrome keeps a hidden NewTabFooterWebView (chrome://newtab-footer/, the NTP footer showing "Managed by your organization" / extension attribution) in every browser window that has displayed a New Tab Page. It stays in the window's accessibility tree for the lifetime of the window, as a sibling of the active tab's AXWebArea.
QueryWebAreaService.fetchScrollArea() returns the first AXWebArea its DFS reaches and only filters the chrome-extension scheme. In such windows the footer WebArea is reached first, so the current URL resolves to chrome://newtab-footer/, no browser rule matches, and the window keeps whatever input source was active (reason=noChanges). Which site is open in the window makes no difference.
Managed/enterprise Chrome shows the footer by default, so this hits every such user after a single ⌘T in a window. Related observation in a comment on #42.
Environment
- Input Source Pro 2.14.0 (build 1182)
- macOS 26.7.1 (25G241)
- Google Chrome 157.0.8103.26, enterprise-managed (NTP footer visible)
- Chrome URL switching enabled, Accessibility granted
- Rule:
DOMAIN example.com → Squirrel (Rime)
Steps to reproduce
The NTP footer must be visible. On an unmanaged Mac, either of these makes Chrome show it:
-
Extension attribution: install any extension that overrides the New Tab Page (e.g. "Speed Dial"). The NTP then shows " has changed this page" in the footer.
-
Management notice: apply any harmless platform policy, which marks the browser as managed:
defaults write com.google.Chrome ShowHomeButton -bool true # restart Chrome; chrome://policy lists it and the NTP footer shows "Managed by your organization" # cleanup afterwards: defaults delete com.google.Chrome ShowHomeButton
Then:
- Add a browser rule, e.g.
DOMAIN github.com → <any CJK input source>; enable URL switching for Chrome. - In a Chrome window, press ⌘T once (the footer is visible on the new tab), then open
github.comin that window. - Switch to another app and back to the Chrome window.
Expected: the rule fires and the input source switches.
Actual: no switch. The diagnostics log shows state.published … reason=noChanges pid=<chrome> and no switch.* entry.
- Drag the same tab into a new window and repeat step 3: the rule fires (
switch.target … reason=appSpecified).
Closing the tab and restoring it with ⌘⇧T keeps the problem; the footer WebView belongs to the window (BrowserView), and only recreating the window removes it.
To inspect what fetchScrollArea() sees, run this from a terminal with Accessibility permission while the affected window is focused (swift -module-cache-path /tmp/swift-cache dump.swift):
import ApplicationServices
import AppKit
let chrome = NSRunningApplication.runningApplications(withBundleIdentifier: "com.google.Chrome").first!
let app = AXUIElementCreateApplication(chrome.processIdentifier)
func attr(_ e: AXUIElement, _ a: String) -> AnyObject? { var v: AnyObject?; AXUIElementCopyAttributeValue(e, a as CFString, &v); return v }
func str(_ e: AXUIElement, _ a: String) -> String { if let u = attr(e, a) as? URL { return u.absoluteString }; return (attr(e, a) as? String) ?? "" }
let win = attr(app, kAXFocusedWindowAttribute) as! AXUIElement
print("AXDocument =", str(win, kAXDocumentAttribute))
var stack = [win]
while let el = stack.popLast() { // same traversal order as fetchScrollArea()
let role = str(el, kAXRoleAttribute)
if role == "AXWebArea" { print("AXWebArea url =", str(el, kAXURLAttribute)); continue }
let kids = (role == "AXTable" || role == "AXOutline")
? (attr(el, kAXVisibleRowsAttribute) as? [AXUIElement]) ?? []
: (attr(el, kAXChildrenAttribute) as? [AXUIElement]) ?? []
stack.append(contentsOf: kids)
}
The first printed AXWebArea is the one Input Source Pro uses. In an affected window it is chrome://newtab-footer/.
Evidence
Replicating fetchScrollArea() (DFS with popLast, same filter) over the AX tree of each Chrome window:
=== window[0] main=1 title=<page on github.com>
AXDocument=https://github.com/...
webArea#1 url=chrome://newtab-footer/ <== picked
path=AXWindow > AXGroup[0/4] > AXGroup[0/1] > AXGroup[0/1] > AXGroup[0/1] > AXGroup[1/4] > AXGroup[0/2] > AXScrollArea[2/3] > AXWebArea[0/1]
webArea#2 url=https://github.com/...
path=AXWindow > AXGroup[0/4] > AXGroup[0/1] > AXGroup[0/1] > AXGroup[0/1] > AXGroup[1/4] > AXGroup[0/2] > AXScrollArea[1/3] > AXWebArea[0/1]
=== window[1] main=0 title=<page on github.com, window never showed an NTP>
AXDocument=https://github.com/...
webArea#1 url=https://github.com/... <== picked
path=AXWindow > ... > AXGroup[0/2] > AXScrollArea[1/2] > AXWebArea[0/1]
Windows with the footer have three AXScrollArea children; the footer is the last one, so the DFS pops it first. The window's AXDocument is correct in both cases.
Diagnostics log (IndicatorDiagnosticsEnabled), affected window:
state.published source=com.apple.keylayout.US reason=noChanges pid=1099
activation.mode mode=autoShow app=com.google.Chrome pid=1099
Same tab after moving it to a fresh window:
switch.target source=im.rime.inputmethod.Squirrel.Hans mode=im.rime.inputmethod.Squirrel.Hans strategy=nil
switch.TISSelect source=im.rime.inputmethod.Squirrel.Hans reason=target status=0
state.published source=im.rime.inputmethod.Squirrel.Hans::im.rime.inputmethod.Squirrel.Hans reason=appSpecified pid=1099
Code path
-
Browser.getCurrentTabURL()(Utilities/BrowserURL.swift) usesQueryWebAreaService.perform()for Chromium browsers. -
QueryWebAreaService.fetchScrollArea()(Utilities/Accessibility/QueryWebAreaService.swift):if element.role == "AXWebArea", element.url?.scheme != "chrome-extension" { return element } -
normalizedTabURL()mapschrome://newtab/andchrome://new-tab-page/to.newtab;chrome://newtab-footer/passes through unchanged intogetBrowserRule(url:).
Suggested fix
Minimal:
if element.role == "AXWebArea",
let scheme = element.url?.scheme,
scheme != "chrome-extension",
scheme != "chrome" // chrome://newtab-footer/ and other internal WebUI panes
{
return element
}
More robust: when the window exposes an AXDocument URL, return the WebArea whose URL equals it (the Comet/Aside path already trusts documentURL), and fall back to the DFS result otherwise. This also covers future hidden WebUI panes such as side panels.
Workaround
New Tab Page → right-click the footer → "Hide footer on new tab page", then close and reopen the affected Chrome windows (per profile).
I can send a PR for either variant.
- Lenguaje dominante
- Swift
- Estrellas
- 3.6k
- Forks
- 144
- Merge medio
- 4 h 16 min
- PR fusionados (30 d)
- 3
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de runjuu/InputSourcePro
-
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
runjuu/InputSourcePro#152 ·
-
Dificultad 3/5 1-2 días Aptitud para principiantes 55/100
runjuu/InputSourcePro#150 ·
-
Dificultad 3/5 Medio día Aptitud para principiantes 30/100
runjuu/InputSourcePro#148 ·
-
Dificultad 3/5 Medio día Aptitud para principiantes 50/100
runjuu/InputSourcePro#147 ·
-
Dificultad 3/5 1-2 días Aptitud para principiantes 56/100
runjuu/InputSourcePro#145 ·
Todos los issues de runjuu/InputSourcePro
Issues similares
-
area: agents area: layout S3: minor
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
manaflow-ai/cmux#34277 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
bug core p3
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
RunanywhereAI/runanywhere-sdks#1258 ·
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
Los mantenedores suelen responder en 1 día
-
album descriptionAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Piwigo/Piwigo-Mobile#669 ·