A while with Google Chrome

A few months ago, I decided to give Chrome a spin for a while. I started out by simply using it to do simple searches on Google and reading articles.
The next step I took was testing it on apps such as facebook and twitter. Then, I progressed to Gmail and complex web apps.

In the following sections, I will outline several pros and cons of Chrome, with some audio examples using NVDA.
/I am exclusively an NVDA user, and thus I never use Jaws, so please don’t ask me how Chrome works with Jaws, because I haven’t tested this. I know how to use Jaws, but just simply do not have a need for a commercial expensive screen reader in my day to day life.

As of June of 2017, Chrome accessibility can be described as mostly sufficient for day to day use, with a few caveats, which are being fixed. In some ways, it is better than Firefox, although it is certainly rough in a few areas.
However, a massive quality control checkup is needed on some areas, as outlined.
Also, keep in mind that Firefox has more than a decade of actual users beating on it and battle testing it, but now has a lot of legacy code that is going to make for some pain in the near future, for a while with the switch to multi process support. Firefox being an old codebase means that it is less buggy, and fantastic, but it also lags in some areas. on the other hand, Chrome is a newer codebase, and has been multiprocess from the start. More on this later.

The benefits

Speed in large complex web apps:

Simply put, Chrome outperforms every web browser in large web apps. If I take Firefox for a spin with Google drive it is very easy to notice lag.
If I press down arrow in the files list, Chromes response time is a lot faster.
This is an audio demo of Firefox, Chrome, and native Google drive.
In Facebook, Chrome is better for speed. I don’t have an audio demo of this, because I don’t want private info from Facebook being exposed to people. However, the effect is not as heavy.
Anecdotally, Twitter seems also faster when navigating from tweet to tweet, although less so than in drive. However, Chrome has other issues on twitter, which make it impractical, and I will discuss that later.
The moral of the story is that Chrome outperforms other browsers in most spaces, at least where speed is concerned.

Security indicators.

One of my favorite things about Chrome is that if you press shift+tab from the address bar, you are placed on a menu with security info. If you press the menu button, a panel expands with a dialog explaining the security settings, and anything this site has asked you permission to use, and the status of whether you granted it permission.
This is very accessible. I was honestly surprised by this. It is very nice.
Also, I get the different level of security indicators such as this site being verified as a company, or just secure, or even no security. (There should be a label of insecure or mixed security on the mixed security menu IMHO).
One of my annoyances with Firefox is as a blind user, I am forced to go view the certificate for this from the page info, and this is painful, and leaves many less experienced users vulnerable to phishing. The padlock is simply not accessible, and the “green” isn’t shown in any way.
I hope that when Google warns users if they put data into a form which is insecure, that this is made accessible, and alerts the user in a similar way to that which we get currently. It doesn’t seem this is blatantly obvious in canary, but it should be in the label of the form or such, so users don’t miss it.
My only annoyance with this is the Google official page seems to not explain this to a screen reader user as well. (In that menu click learn more to see what I mean). They should say what the alt text of this menu is, rather than just the color of the padlock.

accessible extensions bar

The Chrome extensions bar is accessible.
In Firefox, most less than advanced NVDA users, and the clear majority of JAWS users simply can’t get to the addon bar. It requires object navigation with NVDA, and has no built-in keyboard accessible way to get there, and arrow along it. This has always annoyed me, because there should certainly be a way with the keyboard to get to the descriptions 3.
In Chrome, this is a breeze. You simply press f6 from a web page, press tab or shift tab (Either will eventually work), and you are on the bar of extensions.
From here, you can press the arrow keys, do the twist, and eat cake. (Okay, those last two are obviously a joke and a fair bit random, but all people have been commanded to have fun in life, otherwise, they will turn into a prune).
Once on the extensions bar, arrowing along it lets you move to each extension, and you can activate each extension by pressing its button (Assuming the extension is accessible). My only complaint here 2 is that the Chrome bar doesn’t allow you to use single letter navigation.
Firefox doesn’t offer any way for keyboard only users to focus extensions list, or the Firefox menu for that matter (IMO this is a serious shortcoming).

Very simple UI.

The Chrome UI is very simple. For beginners, it gets out of the way.
This is one of the best things about Chrome. I am used to a browser with tons of menus, so it was very weird at first, but it made me realize how little I use the random features that are scattered about. Chrome has most of them still, just not as surfaced.

Shortcomings or annoyances.

Well, those are my noteworthy features. Here are some annoying things. Note that I list general bugs, but I don’t go into super detail on every little bug, because Canary is so rapidly improving that if I list bugs and say every little bug that annoys me, the list will be out of date in a month. That is indeed a good thing.

Chrome live regions are broken.

10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 said Twitter, but alas, I didn’t know!!!
What? twitter is accessible right? Yes, Chrome live region support is broken still in some ways. Some live regions don’t read, and some of them read twice. Aria-atomic is ignored sometimes, and other times, Chrome reads and spells live regions multiple times. In short, this part of Chrome is being worked on and badly needs love.
In a test I did, adding text to pages with innerText and innerHTML yields different results.
Aria-atomic is ignored completely, (It might be fixed in canary based on last minute tests I performed, but there are other broken cases), and acts differently based on the insertion method.
No one supports aria-relevant (From the SR side) so I didn’t test this.
Also, role=”alert” is very different than plain aria-live, and Chrome isn’t marking role of alert with “alert” roles in the IA2 tree.
I need to file a ton of bugs with Chrome for these cases, but I wrote up an aria-live workout page to test things with 3.
there are several controls on the page. The pages divided into 2 major regions, the first is to test polite live regions, and the 2nd is to test assertive live regions.
Within each section, there are many controls.
there are buttons to update the live region for each subsection with the innerHTML and innerText methods, and there are buttons to do each of these things 10 times (to see how well it does at updating the live region multiple times).
The atomic ones should speak hello and then the unique number.
finally, the toggle button which says ” toggle ouch” toggles an alert being thrown every 2 seconds which says ouch. This is designed to test whether the browser properly is working with the alert role.
every time a button is pressed on the page from the regions other than the full-page controls, the status bar updates. The status bar should be treated as a live region as well.
this page is not user-friendly, it’s simply something I wrote so that I can make sure I understand what’s going on before I filed bugs to fix live region support.
in short, this test page that I wrote is giving me the ability to test Chrome live region support against other browsers and the aria spec, and make sure it is working as intended.
when using Google Docs with NVDA in Chrome Canary, the experience was quite decent, even though these applications use lots of life regions. This was after a few bugs were hunted, so the experience will probably be less than stellar on the stable version.

editor bugs

every browser vendor ever has hated doing editors. Editors are extremely hard to get right. After all these years of accessible Firefox and constant effort to make it better, we still don’t have a bug free editor. This is no different in Chrome.
when I say editor, I mean the edit control and associated code for making such things as typing into text fields and complex rich edit support work.
this problem is hard to solve, because there are simply a ton of edge cases. There are no shortage of editor bugs in Chrome, and most of them are very hard to reproduce, which makes reporting them a challenging task. Fixing these bugs is an ongoing job.
I’m sure this will get better over time, but do not be surprised if blank lines report as full of the text on the line before them, or such.

Quality control help needed

Google needs to have stronger accessibility policy in the quality control department.
It is the case that dialogues all over Chrome, (and other Google products) have unlabeled buttons.
This has always been the case, and it seems to happen more with Google products than with other major companies.
It is also common for new apps to be released with tons of easy to fix and easy to catch accessibility bugs, which could be fixed by giving all employees accessibility training and baking awareness of accessibility into developer culture, no matter what role a developer plays.
for a company this size, I am surprised and very disappointed that something as important as the extensions dialog and download manager have simple accessibility bugs such as unlabeled buttons.
A lot of these simple problems, such as links with base 64 encoded gobbledygook text, can be detected with automated testing tools, and could be caught before they ever go live.
Lack of page structure should be caught in code review, and a user should at least be testing core dialogs such as history for usability.
A strong accessibility policy can rocket a company towards fixing these problems. I urge that a strong accessibility policy is implemented in the next few years, which helps to address some of these problems before they ever arise.

Download manager

the download manager has an unlabelled button after each download.
When enter is pressed to download a new file, there is no feedback given to the user that file download is in progress, and until the user presses F6 a few times to land on the new area of the screen which popped up, the user will be clueless to the fact that this exists.
Once a user is in the new download area, they can tab to the controls in it, but the button to open the downloaded files more options is not labeled. Also, it is not clear to the average user that pressing enter on the download will launch the file (potentially causing trouble if it launches an executable program or such).

extensions store

The extension manager’s main page is accessible. However, installation of extensions is where the roses die.
Trying to install an extension is like drinking an entire soda at once. It hurts.
the tabs (I assume) on the top of the page with extensions, apps, and such, are simply links, where a list or tab control would make it feel more like an app.
There are radio buttons, which are half checked labeled “and up”.
Worse, is a very weirdly labeled set of links on the homepage. Snippet below.


This is an excerpt of a chunk of the links on this page which I see.
Along with this, are a myriad of unlabeled links, a complete lack of structure for the entire page, and no headings.
From a usability point of view, this page has no value whatsoever for a screen reader user in its current form, other than the search field.
If rated on Wcag2, it isn’t even level A compliant, not even close. I can’t list everything needing fixed here if I want to, because I don’t know what is being presented.

Other notable page quality control issues.

  • The history page is a structure desert too.
    The same is with the bookmarks page.
    These two pages need a complete accessibility rework.
  • The settings page has seen some love in the last few months. If you still see problems, report them.
  • Some dialogs can’t be read in browse mode, and that issue just got triage, so I know it’s being investigated.
  • There aren’t labels for access keys in the menus.
  • lately, right click menus don’t gain focus when the apps key is pressed. This issue was tracked, and triage.
    However, it was a regression and hasn’t bubbled out of canary, so that’s good news. [5]:

Developer tools

The Chrome Dev tools is not accessible enough. As a developer, I understand that some people depend on dev tools for their job. If dev tools aren’t accessible, a blind person can’t develop for Chrome very easily.
It may be the case that if a developer can’t read the JavaScript errors on their page, they lose their job. I really think dev tools needs careful thought at being fixed in Chrome, and that it isn’t sidelined as a low priority issue, because a recent stack overflow survey found that almost 2% of developers are blind, and only 4% of despondence of the survey chose to disclose their disability. 4
If I as a developer (In that two percent) cannot debug my code, I lose my job. If I lose my job because the dev tools aren’t accessible, it is quite frustrating, degrading, and not pleasant, aside from the fact that blind developers face lots of other challenges getting a job in the first place.


Chrome is becoming a great competitive browser for screen reader users, and it is doing this in leaps and bounds. We have progress to make before it is a polished experience, but finally, there is competition in the accessible browsers market. I am very excited to see accessibility in Chrome now, (Back in the old days, when dinosaurs roamed the earth, and I was a boy, it had no accessibility at all). Jokes aside, I will continue to monitor Chrome closely, and keep using it, along with Firefox, on a daily basis.

The Objects: AutoPropertyObject

In this first article, I will begin doing a deep dive into NVDA’s design. I will explain the most base object common to many components, and how it is used. I assume you have familiarity with the NVDA development Guide, and the Design overview.
Starting at the bottom of the inheritance hierarchy of objects you’ll find NVDA using all the time are the AutopropertyObject, of AutoPropertyType. I aim to give you a basic understanding of how to utilize the full power of AutoPropertyType, butt understanding its source code is an exercise left for the reader of NVDA source code, or advanced developers with an intimate understanding of how python works internally.


Okay, what’s this AutoPropertyObject?

class AutoPropertyObject(object):
    """A class that dynamically supports properties, by looking up _get_* and _set_* methods at runtime.
    _get_x will make property x with a getter (you can get its value).
    _set_x will make a property x with a setter (you can set its value).
    If there is a _get_x but no _set_x then setting x will override the property completely.
    Properties can also be cached for the duration of one core pump cycle.
    This is useful if the same property is likely to be fetched multiple times in one cycle. For example, several NVDAObject properties are fetched by both braille and speech.
    Setting _cache_x to C{True} specifies that x should be cached. Setting it to C{False} specifies that it should not be cached.
    If _cache_x is not set, L{cachePropertiesByDefault} is used.

What in the world is this meta=AutoPropertyType?
To explain this, let’s bring out the NVDA Python Console! Fire up a browser, ensure NVDA is in browse mode, and type this in. Ignore the >>> stuff, that’s the prompt as you probably know by now.

<class 'virtualBuffers.gecko_ia2.Gecko_ia2'>
<class 'baseObject.AutoPropertyType'>
>>> type(type(type(focus.treeInterceptor)))
<type 'type'>

Um … so the type of the tree interceptor (More on those later) is of type virtualBuffers.gecko_ia2.Gecko_ia2. However, things are strange. the type of the type is not type! But it’s type’s type’s type is type.
Most python types are of type type. However, the meta class, which is indeed an advanced topic beyond the scope of this article, changes the type of an object. it’s metta of.
What’s happening here is that virtualBuffers.gecko_ia2.Gecko_ia2 inherits from this AutoPropertyObject with some number of other classes sandwiched in the middle of this hierarchy, thus, it takes on the type of AutoPropertyType. This ‘type’ exists to create some special behavior in the core objects NVDA uses. So let’s discover what AutoPropertyObject does.

The magic starts here!

Assuming you aren’t familiar with python properties, here’s a ten second crash course.
A property is just like a variable, but with magic hooked up. Let’s assume we have a class Rectangle. We instantiate a rectangle with sides 5 and 7, with an area and perimeter.
Let’s get some properties from it.
Here’s class Rectangle.

class Rectangle(object):

    def __init__(self, length=0, width = 0):
        self.__length = length
        self.__width = width

    def length(self):
        return self.__length

    def length(self, length):
    if length < 0:
        raise AttributeError("In this universe, rectangles are tangible thingies.")
    self.__length = length

    def width(self):
        return self.__width

    #Same method name yes, but we have two arguments, so overloading.
    def width(self, width):
        if width < 0:
            raise ValueError("Negative widths result in invalid rectangles. Learn math, and try again.")
        self.__width = width

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return self.length * 2 + self.width * 2

    #You can also use the property method, but that's considered homework for the user.

rect = Rectangle(5,7)
#Let's do stuff.
rect.area #35
rect.perimeter #calculates 5*2+7*2 and outputs 24
#Let's do some horrible things.
rect.area = 55 #ouch, this raised AttributeError? Why?
rect.length = 2 #oh, hey, it worked
rect.length #Hey, looky, it returned 2.
rect.perimeter #calculates 2*2+7*2 and outputs 18
rect.width #Hey, 5 came out.
rect.width = -3 #ValueError is raised. How neat.
rect.area #14 comes out. Wow, it computed that on the fly?

As you can see, properties can allow  us to control what happens when we ask for a value. We can ask python for rect.area, and behind the scenes, a function defined by the property called a getter is asked for the current value. (Getter: get the value associated with the property). If we do rect.length = 1000000, the properties setter is called with the value we want to set. This way, we can make a read only var, or control what val gets set, etc.

Basically, what autoPropertyObject, by way of the AutoPropertyType, does for us automagically, is allows properties to be defined with some fancy method naming. If we read the doc for this class, we see that functions called _get_x and _set_x are mentioned. Why? Also, what’s this caching about?

class TestFancyProperties(baseObject.AutoPropertyObject):
    cachePropertiesByDefault = True
    def _get_x(self):
        return getattr(self, "_x", 1)

    def _set_x(self, x):
        if x < 0:
            raise ValueError("Negative number? Um, I don't think so!")
        self._x = x

    def _get_xSquared(self):
        return self.x * self.x

 def _set_xSquared(self, x):
        raise ValueError("No! You can't change properties of math, not in this universe at least!")

See how cool that is? now, when we instantiate that, and do thing.x, we’ll either get 0, or the previously set x. If we do thing.x = 5, x will magically report as 5 from now on. If we do thing.x*thing.x*thing.x*thing.xSquared*thing.xSquared, you’d think that would be more expensive given that it calls into the _get_x function, right? No. It is actually caching the value of x for one core pump of NVDA. This is good, because thing.x being gotten multiple times will save us from calling the getter. In this example, that is a really cheap operation, but let’s assume that getter is getting the accessible parent of an object. That may easily be a COM call away. We don’t want to write code like this do we?

if self.parent and self.parent.windowClassName == u"window":

If we do that without a cache, that might be 4 or 5 com calls. We can reduce that too 2 com calls with caching getters, and that’s done magically for us.

Take away message!

Basically, if you see a method _get_thing or _set_thing, remember that you can just say blah.thing and set blah.thing = “to a value”. Also, if you can’t find for example, how self.name is defined on an NVDA Object, that would be because self.name is really an AutoProperty. I have one last word of wisdom about AutoProperties (Or dynamic properties).

This is really really really important. I can’t stress this point enough. If I had known this when I started developing NVDA addons, I would have saved myself several hours of wishing I were not debugging silly errors. Any constructor you override, if the class derives from AutoPropertyObject, Must call super. Yes, you really really should always call super if you override something, but let’s face it. We’re all stupidly lazy. The goal of a programmer is 1. Write the least code possible, and 2. write the least comments possible explaining the code, so that we have job security in 20 years still (Hahahahahahaahahahaha boss, take that). Back to the important stuff. If you ever do make the mistake of forgetting to call super in a class that is derived from AutoPropertyObject, no matter how far down into the chain it is, you will get an error to the effect of “I can’t find _autoPropertyCache.” This is because it tries to cache things, but the cache is never created in the constructor.

I hope this was useful. Please feel free to contact me if you have comments or questions. I’m lazy, and can’t be bothered to deal with comment spam bots on this site. Sorry.

Indentone has been deprecated

Say bye bye to the Indentone addon for NVDA! 🙂

A few months ago, I wrote about indentone. The addon is now in NVDA 2016.4, and thus the addon is not necessary. To turn on line indent reporting with tones, select document formatting from preferences, and then select report line indentation using tones (Alt+i). The combobox has 4 options:

  •  Off: No indent is reported.
  • Speech: the old behavior. If you use indentone, you don’t want this.
  • Tones: Just report indents with tones.
  • both speech and tones: Reports with both of them.

A tab is 4 spaces, this isn’t configurable. If your indent gets beyond 72 spaces, or 18 tabs, you will hear speech not a tone. This is so that we don’t hurt your ears. For the technically curious, the work happened on ticket #5906, and #6057 was the pull request.

Musically curious people will love that each space is represented with a quarter tone, giving a tab a whole tone. The first note, (0 indents) is an A3, at 220 HZ. There are 3 octaves of indents reported, and after that, the system resorts to speech. Mixed tab/spaces will report indents, which is something to be aware of. Also, stereo has been removed, as it is unnecessary and counterproductive on users who aren’t using headphones.

With Indentone in NVDA, I wish my fellow coders a much more productive life coding. Please enjoy this feature. Thanks goes to Jamie from NV Access for helping me design the NVDA implementation, Mick from NV Access for helping me track down a bug in the NVDA implementation after I looked at it stumped on how to fix it, Chris Toth of Accessible apps for convincing me to get this thing out to as many coders as possible, and Camlorn for some help getting the correct equation for figuring out what tone to play and the volume hack in the addon but not in NVDA (Yes, I did look at how you did volume in unspoken originally). With Indentone, blind people now have a very natural way to visualize indentation in code, and the excuses about indentation being useless for blind people should be minimized since technology to avoid this has now  been mainstreamed.

Indentone, making NVDA read indents as musical spacial tones.

Attention: This addon has been deprecated. See The indentone deprecation post for details.

I have decided to make an addon that lets NVDA report indents as tones. This for now is not an official NVDA Add-on which has gone through community review (see future work for more reasons). Here is how it works. When you are reading some code or text with indents, if NVDA sees 4 spaces, or 1 tab, it plays a note. Each indent level we increase, the add-on plays the next whole tone up. Example: c3 all the way on your left (one octave below middle c), 0 tabs. D3, slightly farther right, 1 tab. for each level of indent NVDA sees, it plays a note farther to the right, and up that many levels on a whole tone scale. Then, when indent level decreases again, the notes pitch decreases, and the tone moves back to the left a bit. NVDA previously played no tone for no indent (technical reason) (fixed in indentone0.3.0).

The readme is pasted here. for those who don’t care and just want a download link, go to the download heading level 2.

How to use:


Install this addon by pressing enter or double clicking it from the file manager. Then tell NVDA to install it by following the prompts.


When NVDA  would normally speak indents, this addon should activate. If it doesn’t, please contact me.
This addon will detect changes in indent level and beep to inform you that an indent occurred. When the text you are reading is more indented than the last text you were reading, it beeps farther to your right than it did before.
Also, the tone will play one whole tone higher  than the previous indent level would. For example, no tabs will be all the way to your left at one octave below a middle c. The first tab will cause NVDA to play a D3 (one step up), 2 tabs an E3 (two steps up), 3 tabs an fSharp3 (technically 3 steps), and so on.
The 3 tabs will be slightly farther right of the C, and a middle c would be much closer to the center of your body than the c below that.
When the text is less indented than it was before (assuming it was already indented), NVDA will do the opposite. For example, lowering the tone and moving it to the left. The farthest right tab level is 3 octaves higher than the no indent level.

Future work

I may play around with panning the audio dynamically. This would allow me to start the beep at your left, and move it 1 indent unit over a time of about 200 milliseconds. The advantage of this is you could judge the difference in indentation that just occurred, while in parallell hearing the code you are currently editing, even if you don’t musically easily judge whole tone steps.
I am also probably going to experiment with integrating this into NVDA core (I’m going to open up a ticket about this after finals). I spoke about Indentone at NVDACon 2016 in a session about my add-ons. I received much great feedback, and I am excited to continue work on this.

Download and links.


Source Code: