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.
- 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:
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 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:
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.