Adding Support for Regular Expression Search in the Chromium Developer Console
Chromium/Google Chrome is my hands-down favourite browser for developing Web sites in, owing to its incredibly sleek developer tools. I feel right at home in its JavaScript console, for evaluating JavaScript interactively or to inspect logs from a running JavaScript application. However, the latter scenario is somewhat let down by the console’s limited search functionality. At the time of writing, the console only lets you search for plain text on a line-by-line basis. If I want to search for regular expressions, which I tend to do, maybe spanning multiple lines, I’ll have to paste the console contents into a text editor (Sublime, anyone?) and search in there.
To try to get the ball rolling on this "missing" feature, I went ahead and created a feature request. Thankfully, though, Chromium (on which Google Chrome is based) is open-source and welcoming of contributions from volunteers, so I decided I might as well try to implement the feature myself. And so I did. In this post I will document my process of writing the Chromium patch, from my starting out as a completely novice Chromium contributor until delivering a functioning patch for code review.
Bootstrapping
My very first step, as I suppose it should be for any aspiring contributor, was to read the Chrome DevTools contributor’s guide. From the offset, I was pleased to learn that all of DevTools consists solely of JavaScript and CSS, which means there isn’t too much to wrap your head around as you familiarize yourself with the code. The guide itself is very neat and well structured, and I found that it served me quite well throughout. I’ll briefly detail my personal process for getting the development environment up and running on Mac OS X next:
-
Grab the source code from the Blink Git repository:
git clone https://chromium.googlesource.com/chromium/blink
-
Install the bleeding edge version of Google Chrome: Canary. It installs alongside the normal Chrome installation, so no worries there.
-
After cloning the Blink repository, you’ll need to serve the DevTools frontend files. First enter the devtools folder:
cd blink/Source/devtools
. Then, run a Web server within the current directory:python -m SimpleHTTPServer
. -
Now you’re ready to open Chrome Canary to start debugging:
/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --remote-debugging-port=9222 --no-first-run --user-data-dir=~/temp/chrome-dev-profile http://localhost:9222#http://localhost:8000/front_end/devtools.html
. -
Open a new tab in Canary, and visit some Web page of your choosing, e.g. http://chromium.org.
-
Open the developer tools on this page (
Cmd+Alt+J
). -
Return to the first tab ("Inspectable Pages") and refresh the page.
-
Click on the thumbnail of the developer tools of the second tab (e.g., chromium.org). You should now be seeing a tab of DevTools inspecting the other tab’s DevTools. In other words, you should be all set to start hacking!
Modifying Console Search
In order to add my feature, I would first have to figure out how and where console search was implemented. As is my typical MO, I employed a top-down approach to break down the problem. I deduced that the console itself is implemented in a JavaScript "class" called WebInspector.ConsoleView
(Source/devtools/front_end/console/ConsoleView.js). This isn’t where search is handled, though as this is the responsibility of a shared component called WebInspector.SearchableView
(Source/devtools/front_end/components/SearchableView.js). Conceptually, at least the way I understand it, ConsoleView is a specialization (subclass) of SearchableView. Anyway, ConsoleView implements certain methods that get called as necessary by SearchableView (akin to the Template Method pattern, my favourite pattern as it happens).
In particular, SearchableView calls performSearch in ConsoleView whenever a search is to take place. This was the only template method that turned out to be relevant to adding support for regex search. More on this later.
Adding UI Elements
SearchableView is also responsible for creating the UI elements for searching in the console, which it does by adding elements to the DOM (there are no separate .html files). Therefore, I gave the SearchableView constructor a new optional argument, called supportRegex
, to determine whether UI corresponding to regex search should be added (remember, SearchableView is a shared component, and regex search is as of yet only relevant to the console). So, when supportRegex is true, I simply extend the search UI with a checkbox for enabling regex search and an associated label. When said checkbox is toggled, a callback is invoked which either enables or disables regex search depending on the checkbox' value.
Implementing Regular Expression Search
When it came to actually implementing the regex search, I realized that I would need to add a separate template method for this purpose, as it would have to behave entirely differently from regular search. The reason being that plain text search only searches for individual lines that contain the text being searched for, and the current line will be made to highlight its corresponding string. This does not mesh well with regex search, and makes multiline search downright impossible. So, I let plaintext search be plaintext search and designed regex search from scratch as the template method performRegexSearch
.
ConsoleView implements performRegexSearch
as matching the user provided regex against all text in the console (every line concatenated together). Every line is then made to highlight matching strings, and the current matching string is highlighted especially. Since there was no prior support for highlighting the current match especially, I had to add a suitable CSS class myself, named 'current-search-result', to Source/devtools/front_end/inspectorCommon.css. To visualize erroneous regex queries, I also had to add a certain CSS class, 'search-query-invalid', to a new CSS file: Source/devtools/front_end/searchable.css.
This about sums up the changes I needed to make to introduce my feature. If you think there wasn’t a whole lot to it, you’re right; thanks to some clever engineering by the Chromium team, only a minimum amount of code is required!
Re-Loading DevTools Sources
To re-load DevTools sources in Canary, in order to test my changes throughout, I had to press Cmd+R in the DevTools instance debugging the DevTools under test.
Submitting for Code Review
Before submitting the patch for code review, I had to first to install the Chromium depot_tools. This is done by cloning its Git repository and adding it to $PATH:
> git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git > export PATH="$PATH":`pwd`/depot_tools
After doing so, I synchronized my local clone of the Blink repository with the official tree: git pull --rebase origin master
.
And to ensure that my patch was free of formal errors, I ran the Closure Compiler on my code: ./devtools/scripts/compile_frontend.py
My code being free of warnings and errors, I could proceed by making the initial commit, making sure to refer to the number of the issue I had created earlier: git commit -m "#418406 DevTools: Add regex support for console search"
.
After creating the commit, it was time to upload the patch (via depot_tools), thanks to the issue number reference the feature request issue gets referenced automatically in the corresponding code review issue: git cl upload --bypass-hooks
.
The --bypass-hooks
option is to disable certain upload hooks that apparently aren’t necessary, and break for some reason. The patch upload wizard prompted me to enter my Chromium Code Reviews credentials, which I did after creating an account on there. After the wizard finished, I was notified that the a code review issue was successfully created: Issue created. URL: https://codereview.chromium.org/632573002"`
.
Afterwards I announced my reviewable patch at the DevTools mailing list and several Chromium developers signed up as reviewers. The reviewers provided a great amount of useful feedback, resulting in at the time of writing 3 revisions of my original patch. Through reviewer feedback, however, it turns out that work has been going on elsewhere in the DevTools system to introduce regex search, so my patch will have to be revised from the ground up to base itself on said work. This will be the subject of another post.