My time in the browsers world
Published:
The browsers world is really interesting and entertaining, mainly because there is no one browser or browser engine that is “the best”, and they keep pushing each other. Because all of it happens in the open, I fortunately had the opportunity to be part of this world. I’ve been contributing to the Chromium browser engine, working on improving Chromium’s Wayland support in Linux and hopefully making someone’s day a little bit better.
This happened during my time at Igalia’s Chromium team as part of their internship program.
My experience was so great, and I learned lots of technical things, worked with people from around the world, added features and fixed bugs in a project used by millions around the world. I also ended up being a committer at the project (with the @chromium.org email). And all of this is in the open, so let’s dive into more details.
Background
- Chromium is the browser engine powering Google Chrome, Brave, Arc browser, Microsoft Edge, ChatGPT Atlas, and many others.
- Igalia is the second top contributor to the Chromium repository after Google.
- Ozone/Wayland: The component that aims to bring Wayland support to Chromium.
- You can learn more about the recent developments of the Wayland support in this 2-minute talk by Orko at BlinkOn 20.
- As of Chromium 141 (Chrome 141 has just been released on September 30, 2025), Wayland is the default for Linux 🥳.
- People are excited about it on Reddit.
- AbdAlRahman: Oh, this is me! An open source enthusiast who enjoys coding.
Tasks
1. Solve dangling pointers issues in Ozone/Wayland codebase
A pointer dangles when the object that it is referring to is deleted, but the pointer still points to the same address in memory, causing bad things like dereferencing a null pointer. In fact, the last GCP (Google Cloud Platform) incident that caused a global outage was a null pointer issue.
Fortunately, Google has a special type called raw_ptr that has improved memory-safety over raw pointers, as per the documentation:
raw_ptr<T>is a non-owning smart pointer that has improved memory-safety over raw pointers. It behaves just like a raw pointer on platforms where USE_RAW_PTR_BACKUP_REF_IMPL is off, and almost like one when it’s on. The main difference is that when USE_RAW_PTR_BACKUP_REF_IMPL is enabled,raw_ptr<T>is beneficial for security, because it can prevent a significant percentage of Use-after-Free (UaF) bugs from being exploitable. It achieves this by quarantining the freed memory as long as any danglingraw_ptr<T>pointing to it exists, and poisoning it (with 0xEF..EF pattern).Note that the sheer act of dereferencing a dangling pointer won’t crash, but poisoning increases chances that a subsequent usage of read memory will crash (particularly if the read poison is interpreted as a pointer and dereferenced thereafter), thus giving us a chance to investigate and fix. Having said that, we want to emphasize that dereferencing a dangling pointer remains an Undefined Behavior.
You can also pass flags such as DanglingUntriaged to indicate that a pointer might dangle, but its cause has not yet been investigated or resolved.
Fixing dangling pointer issues is important for preventing potential Use-after-Free (UaF) vulnerabilities and improving test coverage. You can read more about this in the documentation. By fixing dangling pointers in the code, everyone is happy 😊.
My first task was to investigate the cause of the dangling pointers found in ozone/wayland and fix them. There are various ways to fix a dangling pointer, and I used several of them in this process.
In this task, I removed 39 dangling pointers and implemented a new approach for cleaning up resources in the test server by passing an optional callback that runs when the resource is destroyed, which improves how resources are managed in tests across ozone/wayland.
List of merged CLs (Similar to PR in GitHub and MR in GitLab):
| CLs | Status | Description |
|---|---|---|
| 6779420 | Merged ✅ | Enhance CreateResourceWithImpl() to accept an optional base::OnceCallback<void()> destroy callback. This callback is registered via a wl_destroy_listener and is invoked when the Wayland resource is destroyed. |
| 6768832 | Merged ✅ | A few different things: Combination of reordering members and reseting several pointers. Involves lots of debugging to figure what’s going on. We even touched code in whole different component. |
| 6883677 | Merged ✅ | A CL without request change 😮 |
| 6827701 | Merged ✅ | Remove dangling pointers in TestSeat by introducing destruction callbacks for MockPointer, TestKeyboard, and TestTouch. This ensures resources are properly reset when destroyed, using base::WeakPtr to preserve a weak reference. |
| 6829867 | Merged ✅ | Add a WaylandWindow observer. |
| 6827269, 6766454, 6779831, 6765073 | Merged ✅ | Reset the pointer somewhere. |
| 6768680 | Merged ✅ | Reorder the cleanup order. |
| 6771305, 6785047 | Merged ✅ | Reorder class members to ensure correct destruction order. |
| 6787208 | Merged ✅ | Use a base::WeakPtr instead of a raw pointer to Wayland buffer. |
| 6786928, 6767414 | Merged ✅ | Code cleanup and removal of unnecessary DanglingUntriaged flags. |
2. Updating the Mutter fork to the latest version
Chromium has more than 250 third party libraries, most are auto-rolled, but some need to be rolled manually, like Mutter (a Wayland compositor) which is used for testing Chromium on Linux. Chromium has a pinned version of Mutter with some custom patches on top, I ported all those patches to a newer version. As you can see, the patch for this in the upstream Chromium issue was merged after 63 patchsets 🙂.
All I can say is that this issue was really tough, but it’s one of those things that are just part of the job.
I also used git cherry-pick for the first time 🎉.
List of merged CLs:
| CLs | Status | Description | Project |
|---|---|---|---|
| 6813650, 6819051, 6829808, 6843036, 6846139, 6846140, 6846299, 6874560 | Merged ✅ | Update the 48.4 fork with Chromium’s custom changes | third_party/mutter |
| 6813489 | Merged ✅ | Update the mutter, gvdb, glib fork in the upstream Chromium repository | Chromium |
3. Wayland text-input-v3: Input window briefly shown at the top-left corner
In the IME support in Chromium, there is an issue where the popup initially appears at the top-left corner.
This is the first issue that involves manual testing and was issued from user feedback. After identifying the cause of the issue, I implemented a workaround that solved it, but it turned out it violates the Wayland protocol specs.
After a few iterations, more triaging, and discussions with my co-mentor (Orko), we figured out that the change needs to be done from the compositor’s side and that any of our workarounds don’t actually fully solve the problem.
I filed an issue to sway and followed up on the issue filled in labwc.
It was a different kind of experience that does not necessarily end up with a merged CL, but more with identifying the root cause of the problem and determine what is the best action to do from all sides, i.e., Chromium developers, compositor developers, and even Wayland developers.
In fact, it ended up all the way to the Wayland developers, and we are waiting for them to decide weather done must be sent thus the composters should add this and solve the issue from their end, or the contrary, and they will relax the protocol. See the discussion here(My filed issue to sway is referenced there 😮)
| CLs | Status | Description |
|---|---|---|
| 6931791 | Waiting for Wayland developers to decide ⏳ | Wayland text-input-v3: Fix input window briefly shown at the top-left corner |
4. Key repeat event
In this task, I implemented a new feature in Chromium to handle key repeat events that were newly introduced in the Wayland protocol.
The change allows repeating keys to be handled from the compositor’s side, which is useful for remote desktop applications such as VNC (Virtual Network Computing). So if you’re using any Chromium-based browser using a remote desktop environment, I hope I’ve made your experience better.
This task was all about gathering information:
- I read through the Merge Request of the new protocol change in the Wayland repository.
- I contacted compositors maintainers, including
sway, andkwin, to see if they support the new change so that I can test it.- The only compositor I found that had implemented this change was
KWin, and it was only available in the gitmainbranch, so I had to build it from source, useKDE, and ended up usingArch Linuxfor a few reasons.
- The only compositor I found that had implemented this change was
In this issue, the testing was “pressing keys on the keyboard.” How come? I was really happy working on this issue.
| CLs | Status | Description | Closed Issues |
|---|---|---|---|
| 6973437 | Merged ✅ | WaylandKeyboard: Handle key repeat state and bump Wayland version to 1.24.0 | 369103602 |
5 Bookmark right click context menu can’t be dismissed and crashes the browser
This issue touches several areas of the Chromium codebase. It involves Ozone/Wayland, Ozone itself, and views (Chromium’s UI framework).
So, in this issue, I ended up looking at this stack trace 🙂 (it’s actually pretty interesting, to be honest). The class hierarchy included classes from several components: ui::Wayland*, views (views::MenuController), ozone, aura, and event handlers. The issue was in views::MenuController::OpenMenuImpl, where the bookmark menu was being dismissed, causing issues that prevented the context menu from being dismissed and led to a crash when dragging and dropping into the folder. We got Check failed: new_parent_menu->HasSubmenu() because views::SubmenuView::Hide was called earlier in views::MenuController::OpenMenuImpl. So, I modified the condition to avoid calling Hide when it’s not needed.
After implementing the fix, it turns out that if you are using mutter, it will crash. In our case, there was a situation where bookmarks would crash the browser because mutter expects the dismissal to happen from top to bottom, and this change violated that.
So, I modified the condition to handle these cases and fixed the bug without violating what mutter expects or reintroducing the previous crash 🥳.
I spent most of my time debugging Chromium with GDB CLI and learned that debugging such a huge project might not be that bad after all. I mean, Chromium is just another Desktop application at the end of the day, nothing to be afraid of. Just watch out that you don’t get overwhelmed :). I also wrote a unit test to ensure that this case, among others, is handled correctly and that future code changes maintain the correct behavior and prevent any crashes.
| Change list | Status | Description | Closed Issues |
|---|---|---|---|
| 6999933 | Merged ✅ | ozone/wayland: Fix bookmark right click context menu can’t be dismissed when coming from an empty folder | 446647004, 446633193 |
6. Input breaks when drag and drop cancelled
Imagine dragging a Google Search link and accidentally dropping it on the same page, and it crashes your tab making it unusable. Well, that’s the issue I’m going to talk about next. Don’t worry though, I’ve fixed it… so it shouldn’t happen again (hopefully 😅).
According to the Wayland protocol, a drop performed event can be followed with a cancelled event. This is the behavior of compositors like KWin.
In Chromium’s Wayland, we were always treating drop performed as a completed drop. So the fix was to handle that drop performed can also mean a cancelled drop.
Looks like a simple thing to fix, which is really is, but in order to figure out what going on and where is the problem, I was drowning in GDB CLI.
Since it was a component I hadn’t touched before, I had to look at a few surrounding classes as well. In total, I went through more than 10 files and classes to identify where the issue was :)
I mean look at this beautiful backtrace:

As you can see from the backtrace above, the issue was caused by a parameter passed in class #0 (in the Wayland layer). It went through a lot of processes that I won’t bore you with, and eventually, we ended up stuck in a loop in #22 (in the Aura layer), which is quite far away and actually part of a completely different layer.
So, a problem in the Wayland layer was causing an issue in the Aura layer (Chromium’s windowing system in Linux, Windows and Chrome OS but not MacOS).
The hierarchy is: Wayland -> Ozone -> Aura, and eventually to ChromeMain() -> main().
See the diagram below: 
I also wrote a unit test 🥳 to ensure that future code changes don’t break this fix or reintroduce the bug.
| CLs | Status | Description | Closed Issues |
|---|---|---|---|
| 7002773 | Merged ✅ | Ozone/Wayland: Treat DND drop performed with NONE action as a cancellation | 447037092 |
7. Numpad delete key not working
Fixing an issue where the Numpad Delete key was not working in the Wayland port. Another issue where the problem could be anywhere in the hierarchy, as you can see: 
Fortunately, after more and more debugging, I figured out where the root cause was. It was in the Ozone layer, specifically in Ozone/XKBcommon, and in the conversions that are used by it in keyboard_code_conversion_xkb.cc.
The problem was that the numpad delete wasn’t mapped in the NonPrintableXKeySymToDomKey() function.
I added it to one of the many conversion files, keyboard_code_conversion_xkb.cc, specifically to the NonPrintableXKeySymToDomKey() function, where we convert XKeySym (X11 keyboard symbol) to a DomKey (Integer representation of UI Events KeyboardEvent.key value.). We later get a key_code from this using NonPrintableDomKeyToKeyboardCode() which allows us to have a valid event.
| Change list | Status | Description | issues |
|---|---|---|---|
| 7032266 | in progress ⏳ | Ozone/Wayland: Numpad decimal key should act as the Delete key when Num Lock is disabled. | 429730008 |
What I’ve Learned
- Working on such a large software project that depends on many external libraries, involves collaboration with developers from other teams and components, and requires coordination with maintainers from related projects, like Wayland protocol developers and compositor developers (
sway,kwin,labwc, and others), has taught me a lot. It made me consider additional factors when implementing a fix instead of having a narrow focus, since a small change in one place can easily cause issues elsewhere.- This experience also made me appreciate how impressive it is that the browser I use “just works” without me having to think about these complexities. Well, not anymore, I guess, fixing it myself is now an option 😄.
- Realizing that Software Engineering involves much more than just coding; gathering information about the requirements, communicating with other developers, discussing solutions, explaining and documenting your findings and even coordinating with other teams and other projects.
- Documenting my work more thoroughly and explaining the reasoning behind each change to make it easier for my colleagues to review, understand, and help clarify any misunderstandings.
- Balancing between being independent and doing my own research, thus learning more and seeking help, and asking questions to clarify things when needed. An important skill that I need to be aware of all the time.
- Become more proactive, this happened after filing issues, or following up on existing ones, in
Chromium(when it was crashing for me) and other projects likeSway(when we needed them to investigate from their side). I learned that filing an issue is crucial and should never be underestimated. Now, if I see a bug or crash in a program, the first thing I do is investigate and try to fix it, then I file a new issue or provide additional information in an existing one. Being proactive and reporting issues when they haven’t been filed yet helps improve the project, as knowing about a problem is the first step to solving it.- Examples:
- Following up on an issue where Chromium was crashing for me: https://issues.chromium.org/issues/436119647#comment16
- Filing an issue in
Sway: https://github.com/swaywm/sway/issues/8884 - Filing an issue in
Chromiumfor a colleague to investigate further: https://issues.chromium.org/issues/435242677
- Examples:
- Learned the software engineering lifecycle, from gathering requirements about the problem, consulting affected users, implementing the change, and writing unit tests.
- Learned to explain my thoughts more clearly, both in writing and verbally. This includes explaining issues, different approaches to solve them, why I think one approach is better than another, and the importance of each approach.
- I also learned to provide reproduction steps and include screenshots or videos when necessary.
Some numbers

- 163 files changed, 43,696 insertions(+), 11,128 deletions(-).
- 9 assigned issues.
- 5 Fixed issues.
- 28 Merged CLs (20 in
Chromiumupstream + 8 inthird_party/mutter). - 8 Reviewers approved merged CLs.
Next steps
The journey has just begun, and the learning never ends.
I’ll continue contributing to Chromium, help my friends get in (already happening ☺️), and hopefully make a small positive impact on users of Chromium-based browsers around the world.
Acknowledgment
I’d like to thank my mentor, Max, and my co-mentor, Orko, for their time and invaluable help throughout the entire internship.
I also want to thank all the reviewers from Igalia and Google who reviewed my CLs and helped me write better code.
