Mojo conversion in printing

[from the renderer to the browser]

For the past few years, Chromium has put effort into the conversion of the legacy IPC system to Mojo.

If you need information about Mojo, please take a look at the documents and a video below.
Igalia also joined the task, and we converted the old-style IPC communication into Mojo messages. The highest priority was the conversion for the messages in //content area, and then we expanded into other components. Regarding the work on Mojo conversion by Igalia, please see the blog post from one of my teammates, Mario.

In this blog post, I’d like to talk about the Mojo conversion in the printing module. I gave a small talk about this during BlinkOn14 lightning talk.

Chromium architecture is based on the multiprocess model and a big amount of IPC messages are for the communication between the browser process and the renderer process. The printing module also communicates with both of them. When I started to work on the Mojo conversion in the printing module, the conversion from the browser to the renderer had already been completed. So, I looked into the messages from the renderer to the browser.

Printing in Chromium

I knew that the printing functionality is great while I was using the Chromium browser, but I was not aware that it has a lot of features with consideration of various environments. On the desktop, you could use it through

  • window.print() from javascript code.
  • Keyboard shortcut (e.g. ctrl+p)
  • From the context menu: print a page or print a selection.
  • The three dots menu
It might have more entry points I don’t know yet.

Once it arrives at the printing main code, it has almost similar code flow but many issues I faced were caused by these various entrance points and use cases. If you have used the printing from Chromium, I believe you’re aware of the printing preview. But, did you know that you could also directly use the printing native menu, skipping the printing preview? I didn’t know it. To disable the print preview,
Command line Switch option: --disable-print-preview
Keyboard shortcut:
  - Preview : ctrl+p
  - Without Preview : ctrl+shift+p
And, the printing module also supports printing on the headless and Android WebView. Whenever the CL related to the Mojo conversion landed, I tried to verify all the possible combinations but it always contained regressions.

Printing with legacy IPC vs Printing with Mojo

Here are legacy IPC messages. You can see how many messages the printing module had and how they were distributed.
Using legacy IPC

And, the next is how they have been changed now. You can see each end point.
Using Mojo
For the interfaces added, you could refer to //components/printing/common/print.mojom.

So why do we want to use Mojo instead of the legacy IPC? Legacy IPC is deprecated in Chromium and Mojo helps to refactor Chromium into a large set of smaller services. For more detail, please refer to this document. With the Mojo conversation in printing, we also removed multiple layers in printing for legacy IPC.

Replacing EnableMessagePumping()

There were a few challenges while working on the printing Mojo conversion. One of them was when I needed to find something to replace EnableMessagePumping(). That is a function that supports pumping messages while a sync message is waiting for a reply. It was not used in many places because it could increase complexity during IPC and the messages used it or the use cases had been cleaned up already. In the printing module, there were two legacy IPC messages using it. After much deliberation on how to handle this part, I defined a sync message and passed a callback that quits the runloop. Then, the nested runloop allows running tasks while it’s waiting for a reply.

A racing issue

There were also some interesting issues. One of them was related to handling the printing result of multiple renderer processes. When there is more than one renderer process by subframes, the browser process manages all the results from each renderer. In that case, there was a racing issue like below.
A racing issue
The sub frame should be handled after the compositor for the main frame is created but it could be handled before the main frame. So, it’s been updated with queuing the sub frame if the compositor is not created and handling the queue after the compositor is created.

Wrap up

With the Mojo conversion in the printing module, I’ve naturally cleaned up classes, structures, and files that are no longer necessary. \o/

There were a few more problems after I thought the work was done, but with the help of many people I was able to solve them safely. Thanks a lot, all people who reviewed CLs, reported issues, and discussed how to fix them.