Of all the search engines I have seen, I like the structure and philosophy of Searx the most. It is open source software released under the AGPLv3+ license. As far as I can tell it doesn’t perform any user tracking. And it is possible for users to run their own instances.
However, Searx gets its search results from other engines, and is often rate limited by them.
And the default settings of Searx.me do not use the safe search filters, which means they display large amounts of pornography and violence when doing image searches. The result is that, even though I like a lot of things about Searx, it currently doesn’t work well enough to be Privacy Browser’s default homepage and search engine.
As such, it is unlikely I will stay with Startpage in the long term. Perhaps I will contribute to Searx or create my own search engine. Finding a good search engine is a little like looking for a Defense Against the Dark Arts teacher.
All of these changes only affect the defaults for new installs. The settings for existing users will not change unless they are manually updated.
Every piece of software as complex as a browser that receives unsanitized information from the internet will eventually be compromised. How often that happens and how damaging the compromises are can be mitigated through a careful design process. Some information about decreasing the damage that a compromise can inflict is discussed on the Core Privacy Principles page under the heading about minimizing the amount of information stored on the device. The purpose of this post is to discuss one of the methods of minimizing how often compromises happen.
An app’s attack surface comprises all the parts of the code that process information from an outside source. A flaw in any one of those pieces of code can allow the app to be compromised. Privacy Browser is composed of code from a number of sources:
Google’s AndroidX and Material Maven repositories, which are released under the Apache License 2.0. These libraries backport features from newer version of Android to older ones. The specific libraries in use can be seen in the build.gradle file. The code from these libraries is added to Privacy Browser when it is compiled.
The free flavor contains Google’s Firebase Ads library, which displays the banner ad across the bottom of the screen. This library is released under the Android Software Development Kit license and is added to the free flavor of Privacy Browser when it is compiled. At some point in the future I would like to migrate to a different ad provider (or create one myself). The code from this library is not compiled into the standard flavor.
In addition to the above code that is compiled into the APK, Privacy Browser also uses a number of standard Android OS system libraries. In the context of Privacy Browser, WebView is probably the most important. But there are a large number of system libraries required for an app to function correctly, including Menu, TextView, Bundle, Activity, and many others. The import section of each Java file shows which system components are used by code in that class. The actual source code of these system components varies based on the version of Android that is installed on your device, which is one of the reasons why it is important to use a system with up-to-date security patches.
Each additional piece of code that is included with Privacy Browser increases the attack surface. I do not personally have the time to read through all of Android’s source code and verify that it does what they say it does and that it doesn’t contain any vulnerabilities. However, because I am only using open source components that are commonly used by many projects, there likely are a number of people who have taken the time to do so. At a fundamental level, a program must trust the operating system it runs under.
From time to time it is tempting to include a library from another source that implements a useful feature. For example, when adding OpenKeychain support for exporting and importing settings, I noticed that there was two ways to do so. One involved compiling a library of their source code into Privacy Browser. This would allow OpenPGP cryptographic operations without the need of the user having OpenKeychain installed. The other was to communicate with the OpenKeychain app using Android’s built-in intent mechanism. This method, of course, requires that the user has OpenKeychain installed. It also requires additional user interaction to accomplish each function.
Now, I have nothing but the utmost respect for the team that builds OpenKeychain. I have no reason to suspect that their code is compromised in any way. But I also am not able to verify myself that their code is not compromised. I do not have the necessary background to audit cryptographic source code. And even if I were able to certify a particular version of their library, I would not have the time to re-audit each new release. This is not just an academic concern; malware infections of common libraries, either through the addition of malicious code by a contributor or via a compromise of the platform where they are hosted has happenedmanytimes in the past.
Even if there is no intentionally malicious code in a library, from time to time there will almost inevitably be security bugs. If the code is included in Privacy Browser, when that bug is exploited the attacker can run any command and access any code in Privacy Browser’s context. But if the code is running in a separate context (like inside the OpenKeychain app), then it can only access that app’s data. Thus, keeping the code in a separate app leverages Android’s built-in security apparatus to decrease the negative impact of any successful exploit.
Privacy Browser 3.1 has been released. This adds a much requested close tab button to the app bar. If there is only one tab, this button will run Clear and Exit.
This release fixes a problem with elements on a web page not being able to scroll left and right that was caused because the view pager kept stealing all the input and trying to figure out if the user was trying to swipe left and right to change pages. The solution was to disable swiping in the view pager as a method of changing pages. Now, the only way to change pages is to use the tab layout in the app bar. This has the additional benefit of making the scrolling of the app bar on and off the screen smoother, because it turns out the view pager was also messing with this input trying to decide if the user was attempting to swipe the view pager.
There is a new splash screen that displays when Privacy Browser starts, which shows the loading status of the blocklists. There has also been a fair amount of effort put into decreasing the load time of the app, resulting in an approximate 50% decrease on many of the devices I have tested. Initially I was planning on converting the blocklist storage into SQLite databases, but I ended up not doing that because the internal structure of the blocklists and SQLite are not directly compatible.
For devices running Android Oreo (8.0, API 26) and newer, the about screen now shows the WebView provider. For example, in the screenshot below, it is provided by Google Chrome.
The Layout submenu in the options menu has been renamed Page. This is similar to the naming syntax in other browsers and should make it easier for people to locate Find on Page. Print and Add to Home Screen were moved from the Share submenu to Page, which seemed like a more natural home with the new name.
The names of the first five settings were shortened. On Android Oreo (8.0, API 26) and newer, the Save Form Data settings is not displayed because it no longer applies.
A number of other changes in this release should improve the stability of the code base, decreasing the number of crashes you should experience
This release features the first complete Turkish translation. The German translation was updated by Bernhard G. Keller, the Italian translation was updated by Francesco Buratti, the Russian was updated, and the Spanish translation was updated by Jose A. León.
The next release will add support for I2P, which is a network, like Tor, designed to hid the user’s IP address.
Back in December 2018, with the release of Privacy Browser 2.15, I removed Google’s Ad Consent Library from the free flavor of Privacy Browser. At the time, the text of the ad consent dialog was updated to reflect that these ads were set to be non-personalized, but that the user was no longer identified as being under age.
Several recent versions of WebView have had problems with proxying. This has manifested most recently with WebView 74.0.3729.136 on Android Marshmallow (version 6.0, API 23) or newer. When using this version of WebView, either provided by the Android System WebView app or by Chrome as described in the instructions for WebView, the app looks like it is proxying, but it isn’t. This problem does not affect Orbot in VPN mode, which routes all traffic from the device through Tor.
It works correctly in WebView version 73.0.3683.90. So, if your WebView is provided by Android System WebView, you can uninstall all updates, which takes it back to an earlier version, and then install 73.0.3686.90 from some place like APK Pure.
From time to time I receive feedback from individuals regarding the layout of privacy browser on small screens. Usually this feedback relates to eliminating an element that they feel is not important enough to warrant the space utilization or diminishing the size of the fonts so that more information can fit on the screen. I am always thankful for these suggestions (I at least remind myself that I should always feel thankful for these suggestions), and sometimes they have led to beneficial changes in the layout. Other times there are reasons for the current design that the person making the suggestion has not considered. I thought it would be helpful to write a post explaining some of these design decisions so that they would be better understood by the community.
When designing Privacy Browser, there are a number of general principles I follow.
Present as much control and feedback to the user as possible.
Use the minimum possible amount of screen real estate.
Minimize the number of taps that are required for common actions.
Reuse existing Android elements as much as possible.
Let me explain of what I mean by each of these points.
Present as much control and feedback to the user as possible
There is both an art and a science to presenting lots of information to the user in a small amount of space in a way that is intuitive and useful. Many programs want to hide important information from users in a misguided attempt to make things “simpler”. Others organize information in a way that is jumbled or difficult to understand. The best programs present all the desired information in an intuitive format that isn’t distracting.
An example of how this design philosophy plays out in Privacy Browser can be seen in the bookmarks interfaces. Privacy Browser’s bookmarks are stored in a SQLite database. Most users don’t want to think about any of the complexities of the underlying structure of the data storage. They just want an easy and intuitive way to interact with their bookmarks. However, there are other scenarios, like troubleshooting database import/export problems, where a power user might need to access or modify the underlying data structure. This led me to create two interfaces, one for general bookmark usage, and one to view and edit the bookmark database values.
Use the minimum possible amount of screen real estate
Nobody likes wasted space, especially on a small phone. Now, this might sound obvious, but to use real estate effectively, each item in the interface must be big enough to see or read, and nothing the user interacts with can be smaller than their finger. Privacy Browser’s two drawer layouts provide a good case study. The navigation menu that opens on the left is generated by a standard Android NavigationView, which provides developers little control over the layout. As you can see in the screenshots below, the interface has been designed to space each entry far enough apart that the user doesn’t accidentally tap the wrong item. Like many default Android interfaces, it uses a relatively small font with a large amount of white space between the lines. On the other hand, the bookmarks drawer that opens on the right is a custom interface that I built. Each entry is also spaced sufficiently so that accidental taps are avoided, but my personal preference is to use larger fonts and less white space. This often has the effect of making users feel that the space is being wasted (because the font is so large), leading them to believe that if the font were smaller more bookmarks could be displayed on the screen. However, the constraining limit on the bookmarks is less about the size of the font and more about the minimum size of the human finger. Consider the three examples below, which are screenshots taken on a Pixel 2 XL running Privacy Browser 3.0.1. With a small system font size, the number of entries in the navigation menu is 13 and the number of displayed bookmarks is 16. When the default system font size is used, the number of entries in the navigation menu remains 13 and the number of displayed bookmarks is slightly more than 14. When the largest system font size is used, the number of entries in the navigation menu is still 13 and the number of displayed bookmarks is 12.
The takeaway from this is that, even thought the font size is larger in the elements I designed in Privacy Browser, the number of bookmarks displayed is greater than if I had followed the standard Android design guidelines used in the navigation menu. It functions as a sort of optical illusion. Even when placing the screenshots side by side, the mind still wants to think that more information is displayed in the navigation menu. But not only does my interface convey more entries for all layouts except for the largest system font size, it does so using nice, big fonts (something I really enjoy even though I have good eyes and something that people with poor eyesight find absolutely essential). It also provides more flexibility to the user by actually adapting the amount of information on the screen to the system font size that is selected, as compared to the standard Android layout, which adjusts the white space so that, on this particular device, 13 entries are all that are ever displayed.
Minimize the number of taps that are required for common actions
I don’t know any developer who doesn’t agree with this in principle, but it can be very hard in practice because 1) different users use different actions, and 2) every time you make something easy to get to you use up precious screen real estate. It is somewhat funny to me that almost every time I make any change to the layout of the options menu I receive feedback from users somewhat along the lines of, “How come you moved my favorite command to a submenu? I use it all the time and now it takes two taps! Also, why don’t you get rid of all the other commands. I never use them and they are just in the way.” As a developer, I can’t just consider how I use the app, but I have to try to think of all the possible ways users might use it.
Figuring out the optimal design ends up being quite a balancing act, one that gets refined over time based on my own personal experiences using Privacy Browser and the feedback I receive from users. As a case study, let me explain the process of designing the tab interface that was released in version 3.0. From the very beginning of the process I wanted to have a tab interface that was displayed directly on the main Privacy Browser window. Most other phone browsers hide their tab interfaces somewhere behind a button or a swipe, so that it takes two actions to do anything with tabs. For some browsers this also involves switching to a secondary activity that covers the entire screen. I knew it wouldn’t be possible to have everything relating to tabs visible on the screen at all times, but I wanted to get at least the most commonly used actions there.
The resulting design uses a TabLayout that is part of the app bar (under the action bar). It is designed so that on almost any device it is possible to see at least two tabs at once. It also has an easily accessible button for adding a new tab, which is a common action and doesn’t take up much additional screen real estate. Because Android already makes the tabs about as tall as a standard finger touch, it made a lot of sense to display the website title in two lines, thus displaying more information.
Initially I thought about adding a close button on each tab, similar to what Firefox or Chrome have on their tablet interfaces. However, I didn’t do this for two reasons. 1) I was concerned that users would accidentally close tabs when they meant to do other things. For example, if more than two tabs are opened on a small device, the user has to drag the tab layout left and right to scroll between them. It would be easy for the drag gesture to accidentally be detected as a tap on the close tab icon. And the absolutely worst kind of interface, worse than having a desired command buried beneath seven layers of submenus, is an interface that mistakes your intentions and does something different than what you just told it to do. 2) I don’t think Android’s TabLayout will allow users to interact with individual elements inside the tab. So the only way to accomplish this would probably be to either modify TabLayout or design an entirely custom interface from scratch. This would be an awful lot of work for something I expect wouldn’t work that well in the end, although there is an open feature request for this and I will probably look into it deeper in the future.
My solution was to place the close tab command as the first entry in the navigation menu, meaning that adding a tab takes one tap but closing a tab takes two (not a very symmetrical experience). Based on user feedback, in version 3.0.1 I added the ability to close a tab that is at the beginning of its WebView history using the back button. This allows tabs that are opened by an intent from another app to be quickly closed with one tap by hitting the system back button on the navigation bar. Not only is this a fairly intuitive interaction for most Android users, but it also takes care of closing tabs in 90% of my personal workflow. It is not a perfect solution, and things will likely evolve in the future, but it represents the current balancing act between usability, screen real estate, and what makes the most sense for the majority of users.
It was as I writing this post that I realized I could place the close button on the left of the TabLayout, similar to how the open button is on the right. This has the advantage of being far enough away from everything else so as not to be a casualty of accidental taps. It is easy to implement because it doesn’t require differentiating taps on different sections of a tab. And, when there is only one tab, it runs Close and Exit, which is a feature I have always wanted to have on the app bar for one-tap access, but I was never previously able to justify the space.
As is usually the case, once you discover a good solution, it seems obvious. But it can often take a lot of work to figure it out.
Reuse existing Android elements as much as possible
Android has a bunch of standard views, widgets, commands, tools, and other elements that can be used to build apps. It is also possible to custom build almost anything with enough work. One of my design philosophies is to use the standard building blocks as much as possible. There are several benefits in doing so. Among them are that Google spends a lot of time making sure these elements scale well between different screen sizes. They work across all the various versions of Android. They are automatically updated when newer versions of Android come out. They scale to different form factors (like tablets) and even to different environments (like Chromebooks). Custom code, on the other hand, requires much more extensive testing to make sure it is going to work across all the various devices out there in the real world. It can require extensive refactoring when new versions of Android come out. It might not adapt to new environments, like Chromebooks. And it won’t automatically update to follow newer theme guidelines, creating a less consistent user experience between Privacy Browser and other Android apps, which increases the learning curve and UX (User eXperience) dissonance.
All that being said, using the standard Android tools is also problematic. Android is buggy, Google isn’t very receptive to bug reports (they barely even read them), and really nasty glitches can continue for years without resolution or even acknowledgment. Also, these tools often don’t do exactly what you want them to do, leading to a lot of compromises and imperfect solutions. And they tend to waste a lot of screen real estate. Although many examples could be given, two will suffice, one where I have chosen to use the default tool even though it is imperfect and the other where I have built a custom solution.
Android has a standard icon for opening the navigation drawer, called the hamburger icon because of the three horizontal lines that look (only a very little bit) like a hamburger bun with a meat patty in the middle. There is a standard tool, ActionBarDrawerToggle, that lays this out in the top left of the action bar and makes it interface with the navigation drawer. The selection, animation, and layout of the icon are all handled by ActionBarDrawerToggle. However, the layout it uses consumes too much white space, as can be seen by the huge wasted area between the hamburger icon and the beginning of the URL text box in the screenshot below. I have considered replacing it with a custom layout, and I might well do so at some point in the future. But the advantage of using a standard tool has so far outweighed the negative of the lost space.
The other example has to do with nested scrolling of the WebView, which allows the app bar to be scrolled off the screen. As described earlier, adding the tabbed interface requires a significant amount of screen real estate. This isn’t really viable unless there is a way to recapture that space while reading a website. Android has an entire set of tools for doing this, but for reasons that make no sense, they do not support doing so with WebViews. So, before I even started working on tabbed browsing, in the last major release of the 2.x series, I implemented an extension of Android’s WebView that worked with nested scrolling of the app bar. It wasn’t easy, but the functionality is so central to what Privacy Browser is trying to accomplish that it was necessary to do so.
Privacy Browser 3.0.1 has been released. This is a bugfix release to correct a couple of serious bugs in the tabbed browsing interface that couldn’t wait for 3.1. A couple of other items were also added to release because they were ready to go in time and resolved less serious bugs.
Because some people don’t want the app bar to scroll off the page, especially on tablet interfaces that are not scrunched for space, there is an option to disable app bar scrolling. However, the way I had it configured, this would disabled app bar scrolling in the WebView, but not in the app bar itself. So, if a user accidentally scrolled up on the app bar interface (for example, when trying to scroll the tab layout left or right) the app bar would scroll off the top of the screen. And there would be no way to get it back without restarting the app or going into settings and enabling app bar scrolling. Having an important part of your interface disappear is a significant enough bug to merit an emergency release.
Similarly, when app bar scrolling was enabled, if a user had multiple tabs open, and one of them was blank (like a new tab), the app bar could be scrolled on and off the screen only on tabs that had a populated WebView, not blank tabs. So, if the user had scrolled the app bar off the screen, then opened the navigation menu by swiping from the left, then closed the tab, if the newly activated tab after the close was blank, there was no way to scroll the app bar back onto the screen. This could be remedied by loading the homepage or a bookmark, or by swiping to another populated tab (if one existed). But those options were not naturally obvious, and the user was often left feeling like the controls had been removed and they were left with a blank or crashed app. Again, interface goes missing; emergency patch release.
I received a crash log that described a rare crash that could occur when a web page finished loading. This was rare enough that I would not normally do an emergency release, but because it was an easy fix I added it into this batch.
With the 3.0 release, I received a lot of feedback, support, suggestions, and bug reports (thank you for all of them). The single most common topic regarded the closing of tabs. There is ongoing discussion about adding a close icon to each tab, which may happen sometime in the future. However, I realized I could improve the functionality of the back button as it related to the closing of tabs.
Prior to version 3.0, if Privacy Browser was at the beginning of the history list and the user pressed the back button, the command would be passed up to the Android system, which would move Privacy Browser off the screen and return either to the app that launched Privacy Browser or to the home screen. In early beta testing I realized this behavior didn’t always work well with tabbed browsing. For example, if a user had multiple tabs open and then switched to an incoming message in another app and clicked on a link in the message, Privacy Browser would reopen with the contents of the link in a new tab. After reading the web page, tapping back would return to the messaging app. This felt natural. But, if a user had been browsing with multiple tabs in Privacy Browser for an extended period of time and then hit back on one of the tabs that was at the beginning of the history view, they would be kicked out to whatever app had been running before Privacy Browser, even if it hasn’t been open for hours. This behavior felt unexpected, especially when other tabs were open. A kind of, “I wasn’t done yet, where are you going?” experience.
At the time, my solution was to make back load a blank page if the WebView was at the beginning of the history. This created a weird scenario where you could cycle between a blank page and the last website by repeatedly pressing back. However, in considering feedback I received about this behavior as well as the desire for a more readily accessible way to close tabs, I realized that, if a tab is at the beginning of the history list and back is pressed, the most natural behavior is to close the tab. This leaves Privacy Browser in the foreground if other tabs are open, resolving the unexpected behavior described in the previous paragraph. And it makes it easy to close tabs that were open via intents from other apps, which is probably about 90% of normal tab usage.
Anyone who has been following these posts for a while has noticed the running thread of limitations caused by Android’s WebView, which is why the 4.x series is going to include a forked version called Privacy WebView. While developing tabbed browsing I discovered that first-party cookies are enabled/disabled by app, while third-party cookies are enabled/disabled by WebView. This means that if the current tab enables cookies, they will also be enabled for any background requests made by any other tabs that are currently open.
There is nothing I can do about this presently, but it will be addressed in the 4.x series. In the meantime, I have added a warning in the settings.
Privacy Browser 3.0 has been released. The major feature is the long awaited tabbed browsing.
Using a tab layout generally works well, and in some cases is even better than I imagined it would be. The favorite icon has been moved from the URL bar down to the left of each tab. This helps with identifying tabs and also frees up valuable space in the URL bar. Adding a new tab is accomplished by tapping the + icon. Closing a tab can be done from the first item in the navigation menu. I considered placing a close icon on each tab, but I was concerned that it would be too easy to accidentally close a tab when trying to switch between them. (For consistency and ease of access, Clear and Exit was also moved up to the top of the navigation menu.)
One of the things I discovered is that Android’s WebView only allows enabling and disabling first-party cookies by app, not by WebView (as is the case with third-party cookies). This limitation will be removed in the 4.x series with Privacy WebView, but until then I have added a warning to the first-party cookies setting.
Because some people don’t like links littering their browser with excess tabs, I created a setting to disable the opening of intents in new tabs. Intents are URLs that are sent from other apps. For example, if an email contains a URL, tapping on it in the email app sends an intent to the browser requesting that it load the URL.
I moved the URL loading progress bar from the bottom of the app bar to the top of the WebView. Otherwise, the progress bar would not be visible when the app bar is scrolled off the screen or when full screen browsing mode is enabled with the app bar hidden.
Another bug was fixed that caused the bottom of the WebView to be cutoff when scrolling of the app bar was disabled. This was caused because the WebView was adjusting the layout assuming the app bar could scroll, which made a section of the bottom of the WebView equal to the height of the app bar not accessible if the app bar did not get out of the way.
This release includes the first full German translation in a while, kindly provided by Bernhard G. Keller. The Italian translation was updated by Francesco Buratti; the Spanish translation was updated by Jose A León; the Russian translation was updated; and the Turkish translation was partially updated.
The next release of Privacy Browser will focus on speeding up the loading time of the app, which currently is hampered by the synchronous loading of the blocklists on the main thread from an inefficient text format that requires extensive parsing.