flypig.co.uk

Gecko-dev Diary

Between August 2023 and September 2024 I upgrading the Sailfish OS browser from Gecko version ESR 78 to ESR 91, writing a daily blog as I went along. This page catalogues my progress, alongside the other browser-related topics I've looked in to since.

Latest code changes are in the gecko-dev sailfishos-esr91 branch.

There is an index of all posts in case you want to jump to a particular day.

Gecko RSS feed Click the icon for the Gecko-dev Diary RSS feed.

Gecko

5 most recent items

17 Jan 2024 : Day 141 #
Preparations are well underway for FOSDEM'24 and I spent this morning putting together a slide template for my talk on Gecko Development. There's not much content yet, but I still have a bit of time to fill that out. It'll be taking up a bit of time between now and then though, so gecko development may slow down a little.

Continuing on though, yesterday we were looking at the Sec-Fetch headers. With the updated browser these are now added as request headers and it turned out this was the reason DuckDuckGo was serving up broken pages. If the headers are skipped a good version of the page is served. But if an ESR 91 user agent is used then the headers are needed and DuckDuckGo expects them to be set to sensible values.

Right now they don't provide sensible values because the context needed isn't available. For example, the browser isn't distinguishing between pages opened at the command line versus those entered as URLs or through clicking on links. We need to pass that info down from the front-end and into the engine.

The flag we need to set in the case of the page being triggered via command line or D-Bus is LOAD_FLAGS_FROM_EXTERNAL:
  /**
   * A hint this load was prompted by an external program: take care!
   */
  const unsigned long LOAD_FLAGS_FROM_EXTERNAL   = 0x1000;
Once this is set it will end up being used in the following conditional inside SecFetch.cpp:
  if (!loadInfo->GetLoadTriggeredFromExternal() &&
      !loadInfo->GetHasValidUserGestureActivation()) {
For the GetHasValidUserGestureActivation() portion of this the logic ends up looking like this:
bool WindowContext::HasValidTransientUserGestureActivation() {
  MOZ_ASSERT(IsInProcess());

  if (GetUserActivationState() != UserActivation::State::FullActivated) {
    MOZ_ASSERT(mUserGestureStart.IsNull(),
               "mUserGestureStart should be null if the document hasn't ever "
               "been activated by user gesture");
    return false;
  }

  MOZ_ASSERT(!mUserGestureStart.IsNull(),
             "mUserGestureStart shouldn't be null if the document has ever "
             "been activated by user gesture");
  TimeDuration timeout = TimeDuration::FromMilliseconds(
      StaticPrefs::dom_user_activation_transient_timeout());

  return timeout <= TimeDuration() ||
         (TimeStamp::Now() - mUserGestureStart) <= timeout;
}
Clearly GetUserActivationState() is critical here. This leads back to WindowContext::NotifyUserGestureActivation() and it looks like this is handled automatically inside the gecko code, so not something to worry about. At least, whether we need to worry about it will become clearer as we progress.

I'm reminded of the fact that back on Day 47 I made amendments to the API to add an aUserActivation parameter to the GoBack() and GoForward() methods of PEmbedLiteView.ipdl and that these probably aren't currently being set properly:
    async GoBack(bool aRequireUserInteraction, bool aUserActivation);
    async GoForward(bool aRequireUserInteraction, bool aUserActivation);
It's quite possible these will need fixing as well, although right now I can't see any execution path that runs from either of these down to HasValidTransientUserGestureActivation(). This is looking for one path amongst a thousand meandering paths though, so it would be easy to miss it.

Go back to focus on LOAD_FLAGS_FROM_EXTERNAL. To accommodate this I've made some simple changes to EmbedLiteViewChild:
--- a/embedding/embedlite/embedshared/EmbedLiteViewChild.cpp
+++ b/embedding/embedlite/embedshared/EmbedLiteViewChild.cpp
@@ -478,7 +478,7 @@ EmbedLiteViewChild::WebWidget()
 
 /*----------------------------TabChildIface-----------------------------------------------------*/
 
-mozilla::ipc::IPCResult EmbedLiteViewChild::RecvLoadURL(const nsString &url)
+mozilla::ipc::IPCResult EmbedLiteViewChild::RecvLoadURL(const nsString &url, const bool& aFromExternal)
 {
   LOGT("url:%s", NS_ConvertUTF16toUTF8(url).get());
   NS_ENSURE_TRUE(mWebNavigation, IPC_OK());
@@ -490,6 +490,10 @@ mozilla::ipc::IPCResult EmbedLiteViewChild::RecvLoadURL(const nsString &url)
   }
   flags |= nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
 
+  if (aFromExternal) {
+    flags |= nsIWebNavigation::LOAD_FLAGS_FROM_EXTERNAL;
+  }
+
   LoadURIOptions loadURIOptions;
   loadURIOptions.mTriggeringPrincipal = nsContentUtils::GetSystemPrincipal();
   loadURIOptions.mLoadFlags = flags;
This change will have a cascading effect through qtmozembed and potentially all the way to sailfish-browser. But the easiest way for me to figure out what's missing or needs changing is for me to build the package find find out what breaks.

So for the first time in a long time I've set the gecko-dev building once again.

Tomorrow I'll find out what sort of mess I've caused.

If you'd like to read any of my other gecko diary entries, they're all available on my Gecko-dev Diary page.

Comments

Uncover Disqus comments