#46 window.name wrapper and WrapHelper.domainChanged
Closed: Fixed 2 years ago by polcak. Opened 2 years ago by polcak.

Firefox implements window.name wrapper in a way that the content is cleared if the users goes to a different eTLD+1 domain. We remove the content with each visited page. It would make sense to replicate Firefox behaviour. We need to have a way that informs the wrapper that the user visited a new domain.

Can code builders generate a cross-browser compatible constant notifying wrappers that the tab visits a domain that is different to the previous one?

Like the user visited:

example.com/ -> WrapHelper.domainChanged = true (I do not care much right now about the first notification in the tab)
example.com/2.html -> WrapHelper.domainChanged = false
example.com/3.html -> WrapHelper.domainChanged = false
another.org/ -> WrapHelper.domainChanged = true
another.org/foo -> WrapHelper.domainChanged = false
example.com/ -> WrapHelper.domainChanged = true

Giorgio volunteered to implement WrapHelper.domainChanged.


Hello Giorgio,

I started to work on this issue. I have a couple observations for which I need a clarification.

I started with:

 diff --git a/common/level_cache.js b/common/level_cache.js
index ecdff38..8715e2d 100644
--- a/common/level_cache.js
+++ b/common/level_cache.js
@@ -106,6 +106,9 @@ browser.runtime.onSyncMessage.addListener(contentScriptLevelSetter);

 DocStartInjection.register(async ({url, frameId, tabId}) => {
        let configuration = await getContentConfiguration(url, frameId, tabId);
+       configuration.newUrl = url;
+       configuration.oldUrl = TabCache.get(tabId).url;
+       console.log("JShelterDevel", configuration);
        return `
                window.configuration = ${JSON.stringify(configuration)};
                if (typeof configureInjection === "function") configureInjection(configuration);

I see in the debug console that configuration is amended as expected. But:

diff --git a/common/document_start.js b/common/document_start.js
index ddcc4be..54438c0 100644
--- a/common/document_start.js
+++ b/common/document_start.js
@@ -74,9 +74,22 @@ function configureInjection({currentLevel, code, wrappers, domainHash, sessionHa
 }

 if ("configuration" in window) {
+       /**
+        * This happens:
+        * * User navigates from a origin to a different origin
+        */
+       console.log("JShelterDevel configuration window");
        console.debug("Early configuration found!", configuration);
        configureInjection(configuration);
 } else {
+       /**
+        * This happens:
+        * * User navigates to a page from the same origin, including navigating from
+        * https://www.fit.vut.cz to https://www.vut.cz
+        * * When an iframe is created
+        * * When a new tab is created
+        */
+       console.log("JShelterDevel configuration background");
        /// Get current level configuration from the background script
        configureInjection(browser.runtime.sendSyncMessage({
                        message: "get wrapping for URL",

See the comments above. What I see exactly matches my needs (even better than described above). When the configuration is retrieved from background, I do not want to remove window.name content (although I am not completely sure about the iframes, that needs further testing). When the configuration is retrieved from window, I will very likely always want to set window.name to empty string (but I will of course check).

What bothers me is that I did not expect so many retrievals from background and I fear that my observations are flawed. I mean, should a user changing origins (or TLD+1) trigger background retrieval, I would not be able to detect that. Can you confirm that my observations are correct?

Also, I tested only in Firefox, it might be different for Chromium-based browsers.

What I do not get is that DocStartInjection.register() from level_cache.js is called but as far as I understand that code is then completely useless as the configuration is not set on the window.

Actually I think the preferable approach to window.name sanitization would be tracking domain changes using a webNavigation listener and zapping window.name with tabs.executeScript() from webNavigation.onCommitted(), because otherwise there's no reliable way to tell what's the previous domain (TabCache would kinda work, but for top-level loads only).

I do understand that wouldn't integrate easily into the whole wrapper configuration machinery and you would prefer to have the necessary "domainChanged" information on the content script side, therefore I'm trying to build a new NSCL "NavCache.js" service which stores the information above (currentURL and previousURL for each tabId/frameId) and could be used directly by getContentConfiguration(), no matter if called by the messsage handler or the DocStartInjection registered callback.

Yes, I was also thinking about doing the sanitation during the navigation event. And it might work with a limited work.

  1. I will change the window.name wrapper to do nothing. But it will be displayed by the JSS UI.
  2. We will create a new set of files called let's say navigation-[stage]-S-*.js. The only file will be navigation-onCommitted-S-HTML.js with the transformed window.name wrapper.
  3. navigationS-*.js will be handled by the build scripts similarly to wrapper files and they will automatically register for navigation handlers. Probably with some helping code like wrapping.js.
  4. We will use code like:
browser.tabs.executeScript({
    tabId: tabId,
    allFrames: false, // I do not see a need to propagate the event to nested frames as this will be destroyed anyway
    code: `some_callback('${nextUrl}', '${previousUrl})`,
    frameId: frameId,
    matchAboutBlank: true,
    runAt: "document_start",
  });

(5.) This will be called from getContentConfiguration because that will provide the URLs, and tab/frame id. But I could also see JShelter use code like:

browser.webNavigation.onCommitted.addListener(
    function({tabId, nextUrl, frameId}) {
        ... call executeScript here ...
    }
);

The only problem is that we need to access TabCache from this code to get previousUrl().

Or do you have a different workflow in mind?

The mechanism is in place https://pagure.io/JShelter/webextension/c/93fb015c0f5c3425d88494d29b87c461087016e3?branch=nameZap. We selected a different approach compared to the opening text.

Metadata Update from @polcak:
- Issue close_status updated to: Fixed
- Issue status updated to: Closed (was: Open)

2 years ago

Login to comment on this ticket.

Metadata