Tip:
Highlight text to annotate it
X
CHARLES L. CHEN: Hi, everyone.
So we're here to talk about advancing web accessibility
with ChromeVox.
I'm Charles Chen.
I have two of my colleagues here with
me, Volker and David.
You guys want to say hi to everyone?
VOLKER SORGE: Hello.
DAVID TSENG: Hi, everyone.
CHARLES L. CHEN: OK.
So let's get started.
Here's a brief overview of what we'll be
talking about today.
Stat off with an introduction about what is ChromeVox.
David will take you on a walk through the DOM.
Volker will discuss reading math.
I will talk about how to use ChromeVox APIs in your own
applications and web apps.
And then we'll have a conclusion to sum up what
we've talked about.
So with that, what is ChromeVox?
Well, ChromeVox is a screen reader for Chrome which brings
the speed, versatility, and security of Chrome to
visually-impaired users.
What's special about ChromeVox is that we built all of this
with web technologies, such as HTML5 and JavaScript.
So there's no impedance mismatch between what
ChromeVox does and the rest of the web and your web apps.
This allows us to advance accessibility at the same rate
as all of you innovate and create new exciting web
applications and really push the boundaries of what is
possible to do inside the browser.
There are huge benefits for end users and web developers.
For end users, you get a screen reader that's built
into your system.
On any Chrome OS machine, you just press Control-C, and it
will start talking.
So it's right there.
It's also available on desktops.
And for web developers, you get something really unique.
You have a screen reader that works inside your browser that
fits with your development workflow.
You can do some work, run ChromeVox on it, and then
listen to it and see what it sounds like.
Because it is built with web technologies, there isn't any
sort of mismatch between what you would expect, in terms of
you can do with JavaScript and the underlying platform.
The underlying platform is JavaScript and web.
So any time you want to do something that's custom, there
is a way for you to do it.
And we've opened up several APIs to help you create better
auditory experiences on the web.
And with that, I will now hand it over to David, who will
give us an overview of how you walk through the DOM.
Probably just a little bit to your right, OK?
OK.
Perfect.
DAVID TSENG: Thanks, Charles.
Good evening, everyone.
My name is David Tseng.
I'm a software engineer on the Accessibility Team.
I work on ChromeVox and Chrome OS.
So tonight I'm going to give you a behind the scenes
insider look at how ChromeVox works under the hood.
So as you can see above on the slide, to the left you have a
pretty innocent looking piece of markup.
It's pretty simple.
And unordered list of links and an editable text, input
type equals text, and a button.
So if you ask yourself, well, how does a screen reading
actually take something like this and generate a
description and make it possible for a keyboard-only
user, or someone who doesn't see the screen, to explore
this content?
How does someone do that?
I can take you through some alternatives and how ChromeVox
actually does it.
So you can imagine, I could just take all of the text
content inside of the unordered list
and just speak it.
So the problem with that is we don't get any of the semantics
such as this is a list and these are some links.
So that's probably not a good idea.
How about, say, let's let the user move from the structure
of this markup, so we can imagine a system where we let
the user land on the unordered list, let them move down into
the links and move about in the links and move out, then
go to, say, the editable text field.
That's a little closer to what ChromeVox does.
So what it actually does ChromeVox do?
Well, we centered around and we converged on the idea of
granularity.
Let me define what a granularity is.
A granularity consists of two things, some notion of what a
leaf node is, so how deep did we go in this tree structure,
and what it means to go to a next or previous item.
I'll go ahead and show you what our base granularity is,
which we call Object.
Now for this, we actually define a leaf node as any sort
of interesting element, such as a link or a button or an
editable text field.
and the next or previous item just as one of these
interesting items.
So with that, I'm going to go ahead and enable ChromeVox and
show you what it's like to navigate in this very
sequential fashion.
CHROMEVOX VOICE: Enabling spoken feedback.
Article list with four items.
Web, link list item.
DAVID TSENG: So this is the first interesting item.
And you'll notice that ChromeVox said article and the
text of the link and the role, link, and played an earcon,
which is analogous to an icon, just a sound
representing some concept.
So the article, which you heard, is the context, which
means that this markup was surrounded by something that
was an article, an audio role.
All right.
So if I continue navigating, I'll end up on another link
CHROMEVOX VOICE: Maps, link list item.
DAVID TSENG: And another link.
CHROMEVOX VOICE: Images, link list item.
Gmail, link list item.
Google.
DAVID TSENG: And that's actually a paragraph.
So that's a basic introduction to one of our first
granularities, object.
So what are some other interesting granularities?
Well, we also have defined a character granularity.
And using that definition I just gave you,
what does it mean?
Well, it just means that the leaf node is now a text node,
and the next and previous items are just the next and
previous characters within that text node.
So I have a command in ChromeVox that says Change
Granularities.
CHROMEVOX VOICE: [INAUDIBLE]
character, G, O, O, G, L, E. Echo.
DAVID TSENG: I was able to scan that text node just by
walking through the characters.
And you also heard a nice feature of ChromeVox that does
a phonetic map for the letters.
So if there's any ambiguity in the text-to-speech, such as an
engine that doesn't have the clearest announcement of
characters, we can give users another hint after a little
bit of a pause and speak the word that phonetically can
describe that character.
So we have some other granularities, the usual ones
that you would expect, word and line.
So those are interesting because they break on
different delimiters.
And so the next and previous definition of the granularity
is the only thing that we need to change there.
Beyond these basic granularities, ChromeVox
supports tables.
And we're able to get the tables to fit into this
definition by saying, OK, next and previous are rows, and
leaf nodes are just the rows' items elements.
And finally, we have some interesting developments that
just got released with ChromeVox 27, which was just
put up on the web store, that knows how to
deal with math content.
And with that, I will invite Volker Sorge to talk more on
that subject.
VOLKER SORGE: Thank you very much, David.
CHROMEVOX VOICE: Disabling spoken feedback.
VOLKER SORGE: So my name is Volker Sorge.
I'm actually a Senior Lecturer at the University of
Birmingham in the UK.
But I'm spending a year working with the ChromeVox
team here in California in order to work on getting
mathematics spoken with the ChromeVox engine.
And it is a sad fact that what is still the biggest obstacle
for a fully inclusive education for
visually-impaired students is that much of the scientific
content that's available out there is practically
inaccessible.
So at the ChromeVox team, we've realized this, and we're
trying to make some way towards making some of this
content accessible by at least making the mathematics that
can be found on the web out there accessible via a screen
reader
And as a consequence, we implemented aural rendering
for mathematical content in ChromeVox.
And if you're not familiar how math really works on the web,
math is generally given in MathML format, or it's being
rendered from either MathML or other formats using MathJax.
And with ChromeVox, we can now deal with both types of
mathematical content that's on the web.
As a consequence, spoken math is now supported on all
platforms that support Chrome.
So if you were within a Chrome browser, you can use ChromeVox
in order to have math spoken.
And what might be particularly interesting for developers, of
course, is that if you're, for instance, developing the Epub3
reader, you can leverage all the work we put into ChromeVox
using the WebViews interface.
And thereby, for instance, have spoken math on Android
tablets or smartphones.
Right.
So let me dive into the details a bit, how math is
actually being rendered.
Usually, it's rendered more beautiful than this.
And I'll just tell you why this is the case.
Here.
This is how math is being rendered.
And you might recall this equation.
This is the solution to the quadratic equation.
Actually, it's two solutions.
And the way it's being given generally on the web is by
using a MathML markup language.
MathML, as you can see on the left of this slide, is a
fairly straightforward XML representation of what you
have up there as the mathematical formula.
So you can fairly easily map those, the x to the x and the
equals to the equals.
And then you have kind of a structured tree representation
of what the math formula is there.
Unfortunately, not every browser renders MathML
straight away.
And as a consequence, there's a tool out there, which is
called MathJax, which can render math in
all browsers similarly.
And as a matter of fact, on this slide actually we used
MathJax to render the slide.
And notice the little hiccup we had in the beginning
because the rendering sometimes breaks a bit and you
have to do a little reload.
So on the right-hand side of the slide you see how,
actually the MathJax looks like.
So if you have, for instance, the MathML in your DOM
originally, then MathJax will replace it in the live DOM in
your browser with the right-hand side.
And then you see immediately this is a lot less obvious
what the mapping between the actual elements of the
mathematical formula is, as a lot of it is obscured by some
of the markup that is necessary for the rendering.
All right?
Nevertheless, within ChromeVox, we can speak both
MathML and MathJax similarly.
So the aural rendering is then done normally doing the text
navigation.
And I'll show you how this then sounds.
Let me switch on the ChromeVox engine again.
CHROMEVOX VOICE: Enabling spoken feedback.
VOLKER SORGE: And now we go to the next math expression.
CHROMEVOX VOICE: x equals minus b plus/minus square root
of b squared minus 4ac divided by 2a.
Math.
VOLKER SORGE: Right.
And so this is how it's being pronounced while it's in
regular text.
So you can hear we are playing a bit here with certain
changes of the speech.
For instance, we're changing the rate and the pitch when we
go into the nesting of, say, the square root or of the
numerator of the division.
Also, we change the pitch when we go into sub and
superscript.
As a consequence, you can hear where the square root actually
ends and where then the division starts again.
Nevertheless, in many cases this might be too fast for you
when you actually listen to this expression, particularly
if it's a very large expression.
What you then would like to do and what we provide--
CHROMEVOX VOICE: Disabling spoken feedback.
VOLKER SORGE: Let me switch off feedback first.
What you then would like to do is actually start exploring
the mathematical expression a bit further.
And indeed, in ChromeVox we now provide some functionality
in order to do this.
So what you could hear originally when you listened
to the formula is that it's being announced as a math
expression.
CHROMEVOX VOICE: Enabling spoken feedback.
x equals minus b plus/minus square root of b squared minus
4ac divided by 2a.
Math.
VOLKER SORGE: Right.
Now it announced math.
Now we know we have a math expression under our cursor,
effectively.
And now we can actually explore it, if we want to.
So let's start exploring it.
That's ChromeVox backslash.
CHROMEVOX VOICE: Entered math.
[EARCON SOUND]
x equals minus b plus/minus--
VOLKER SORGE: I'll stop that speaking here.
But you could hear a little earcon that tells you now
we've ended the math expression.
Now we can start exploring it.
And you can now start exploring it just regularly
with your cursor keys.
CHROMEVOX VOICE: x equals-- x.
VOLKER SORGE: All right?
So we can start the first thing and then--
CHROMEVOX VOICE: Sticky--
Customizing Math.
VOLKER SORGE: Oops.
Now I've made a mistake here.
Sorry about that.
CHROMEVOX VOICE: Disabling spoken feedback.
VOLKER SORGE: Let's go back.
CHROMEVOX VOICE: Enabling spoken feedback.
[EARCON SOUND]
Wrap to top. x equals.
VOLKER SORGE: Let's enter the expression again.
CHROMEVOX VOICE: Entered math.
[EARCON SOUND]
x equals minus--
x equals minus b plus/minus square root
of b squared minus--
VOLKER SORGE: OK.
I'll try this one time.
I hope this time it's going to work.
We enter the expression.
CHROMEVOX VOICE: x equals minus b plus/minus square root
of b squared minus 4ac divided by 2a.
[EARCON SOUND]
Wrap to top. x equals minus b plus/minus--
[EARCON SOUND]
Entered math.
VOLKER SORGE: Now we're in the math expression.
CHROMEVOX VOICE: --minus b plus/minus square root of--
VOLKER SORGE: Let's try this again.
CHROMEVOX VOICE: --b square.
VOLKER SORGE: Nope.
I'm sorry.
This is the effect.
Sorry.
That's the demonstration effect.
If you come to our Sandbox, I'll demonstrate
this to you in detail.
I'm not quite sure why this currently doesn't work.
So the idea is, if I had been able to show that to you now,
that you can actually enter the math expression and then
start walking the math expression.
Currently, this traversal follows fairly
the syntactic structure.
So you can listen to it, x equals and then the expression
on the right-hand side of the equality.
In the future, what we're currently working on and what
will be released soon is that we have a more systematic way
of actually exploring the mathematical expression in a
particular way to customize this exploration.
CHROMEVOX VOICE: x equals minus b plus/minus.
x equals minus b plus--
x equals minus b-- x equals--
x equals--
x--
VOLKER SORGE: Ah.
There you go.
Sorry.
Now we're actually on the expression.
Now it actually works.
CHROMEVOX VOICE: Equals.
VOLKER SORGE: So now we're actually exploring the
expression.
If you can look, we're exploring the left-hand side.
If I go back--
CHROMEVOX VOICE: x--
VOLKER SORGE: --x--
CHROMEVOX VOICE: --equals--
VOLKER SORGE: --equals--
CHROMEVOX VOICE: --minus b--
VOLKER SORGE: Now we get the right-hand side of the
expression.
CHROMEVOX VOICE: --b squared minus 4ac divided by 2a.
VOLKER SORGE: And now we can start exploring further.
So we get a bit further.
CHROMEVOX VOICE: Minus b plus/minus square root of b
squared minus 4ac.
VOLKER SORGE: So if you still haven't fully understood
what's in the expression, you can go further.
CHROMEVOX VOICE: Minus b plus/minus square root of b
squared minus 4ac.
VOLKER SORGE: And now you can start
entering the square root.
CHROMEVOX VOICE: b squared minus 4ac.
VOLKER SORGE: And so on, and so forth.
So this is the basic idea of how to explore the
mathematical expression.
And as you can see, we followed pretty much the
syntactic structure as it is.
My apologies that I fat fingered this and it didn't
work from the beginning.
Obviously, now we're in the expression.
Now we can also leave the expression again.
CHROMEVOX VOICE: Cut.
VOLKER SORGE: And then once we're outside the expression--
CHROMEVOX VOICE: Disabling spoken feedback.
VOLKER SORGE: --we can then actually continue working with
ChromeVox as normal.
Right.
Now one of the major things about mathematics and speaking
mathematics is, of course, that it can be very different,
four depending on the mathematical domain you're
working with and also depending on the particular
style of mathematics you're doing.
As a consequence, we've built everything in ChromeVox in a
very customizable fashion, which means that one can
contribute to the way mathematics is spoken.
Say if you want to work on your favorite mathematical
topic and you want ChromeVox to be able to speak all things
correctly, then you can contribute speaking rules for
the speech engine or for the ChromeVox engine as well as
just mappings for separate characters.
For instance, here I've put down a couple of equations on
the screen.
One is just a division followed by a multiplication,
a divided by b times c.
And on the right-hand side, if you're familiar with natural
deduction calculations--
some with you might be from your logic class--
then this is a natural deduction.
And either way, you want it pronounced differently.
On the one hand side, you want it to be pronounced as divided
by, and the other side you want it to be pronounced,
let's say, the second part of the rules follows from the
first part of the rule.
And I've put down the simple JavaScript functions that
allow a user or a contributor to customize our speech rules
accordingly for the different expressions that you have.
In addition to just customizing them by entering
effectively different orders in which things are being
spoken and entering different types of strings that are
being spoken.
You can also make optional changes to, say, things like
pitch, rate, volume, as well as pausing for effect, as we
had earlier in the quadratic rule formula.
Right.
This is one way of customizing it.
And then how can this actually be used by people that want to
develop, say, an Epub3 reader with it?
Well, we have a fairly easy way to interface to the
mathematics as to everything in ChromeVox.
And if you just pass a math node that you come across in
the DOM at the right level to ChromeVox, either as MathML or
as the rendered MathJax in the DOM, then we have a fairly
simple API function with which the note gets spoken.
And you can leverage all the machinery that we put into
ChromeVox in order to speak mathematics with your own app.
And the particular API function here is just syncing
to the particular math node.
And there are some other API functions, which I'll now ask
Charles to explain to you in more detail.
Thank you.
CHARLES L. CHEN: Thanks, Volker.
So we've talked about how ChromeVox works as well as
some of the cool new math features that are coming out.
Let's see how you can use ChromeVox in your own web
application.
Let me just refresh this page here.
OK.
OK.
So why would you want to use ChromeVox APIs?
Well, these APIs give you, as the
developer, a lot of control.
It helps you to help give ChromeVox hints about how it
should be speaking content.
It lets you give ChromeVox hints about where the user is
in your application.
And the most recent feature that we added with our last
release of ChromeVox has been the ability to get at what the
user is trying to do on your web application.
So for example, on ChromeVox, as David was showing earlier,
when you navigate, you can navigate structurally.
So you can say, jump to the next list item, or go to the
next link, so on and so forth.
But what if you, as a web developer, had a web
application where it had semantic structure to it but
that wasn't necessarily exposed to the user?
If the user wants to go to the next heading, your web app may
be much better equipped to do that than ChromeVox.
And so, in ChromeVox, wherever the user tries to do an
action, we actually send it to the underlying web app so that
the web app gets first dibs on handling it.
And so if it can handle it better, it can do it instead
of ChromeVox and just pass the result back.
There's full documentation available on this link, and
these slides will be made available after I/O. But let's
go through some code samples of how you can apply this in
your applications.
So one thing that could be really useful to you as a web
developer is to be able to speak custom messages.
So let's see how this would sound.
CHROMEVOX VOICE: Enabling spoken feedback.
CHARLES L. CHEN: OK.
So sometimes you may be doing something in your web
application where visually it's obvious what's happened.
But it would be useful to give someone who's using a screen
reader, such a ChromeVox, an idea of what you actually did.
So right now, the code there is how I am going to make
ChromeVox speak this next message.
CHROMEVOX VOICE: Code highlighting off.
Code highlighting enabled.
CHARLES L. CHEN: OK.
Code highlighting enabled.
And when I turn it off--
CHROMEVOX VOICE: Code highlighting off.
CHARLES L. CHEN: OK.
So as you can see, visually it was obvious, because the code
that I had bolded was immediately highlighted.
Everything else faded out.
But it's nice to be able to auditorial convey that
information.
And so all it took was this one line of code here.
CHROMEVOX VOICE: Code highlighting enabled.
CHARLES L. CHEN: You just call ChromeVox Api.speak, give it
this string of text, and it just speaks it.
Pretty simple.
CHROMEVOX VOICE: Speaking custom messages.
Heading 3.
Sticky mode disabled.
CHARLES L. CHEN: OK.
CHROMEVOX VOICE: ChromeVox APIs.
Speaking custom messages.
Function speak current slide.
CHARLES L. CHEN: Now what you notice there is
I flipped the slide.
And it actually started reading the slide to me.
So when it did that, this is another example of using a
ChromeVox speech APIs is that you can
make it speak something.
And I'm actually beginning to lose my train of thought here.
I probably should have practiced more.
But this is actually why it's really cool to
have speaker notes.
So let's try that.
CHROMEVOX VOICE: Show how easy it was to add these AP is to
the I/O slide template.
CHARLES L. CHEN: Oh, yeah.
OK.
That's what I'm supposed to be talking about.
So as you can see here, when I press the key command to bring
up the speaker notes, it actually spoke
those notes to me.
And now if I dismiss them--
CHROMEVOX VOICE: Notes hidden.
CHARLES L. CHEN: --it tells me notes hidden, and it
synchronizes me back to the top of my slides.
On the other hand, if I try this on a slide where I don't
have speaker notes--
CHROMEVOX VOICE: ChromeVox APIs.
No notes available.
CHARLES L. CHEN: --it tells me no notes available.
So I was actually pretty lucky there that I forgot my content
on the side that has speaker notes.
CHROMEVOX VOICE: ChromeVox APIs.
Speaking custom messages.
Func code highlighting enabled.
CHARLES L. CHEN: OK.
And as you to see, again, it's really simple to do this.
Again, it's just a simple ChromeVox API speak.
By the way, you'll notice that, in this case, I have a
couple more arguments in there.
And these arguments allow me to control the voice.
So if you listen carefully--
CHROMEVOX VOICE: Show how easy it was to add these APIs to
the I/O slide template.
CHARLES L. CHEN: Notice how that voice
was at a lower pitch.
So that's a way to give the user a little bit more flavor.
In this case, it's to indicate that this in a slide.
It's speaker note and not main content.
CHROMEVOX VOICE: Notes hidden.
ChromeVox APIs.
CHARLES L. CHEN: Now another thing that's useful is if
you're navigating for your application and a user wants
to suddenly investigate more or try navigating from a
certain point, it's useful to synchronize the user's
position with where they actually are.
And ChromeVox makes this really simple.
All you have to do is just call API sync to node, and
you'll basically tell ChromeVox that, hey, the user
is over here right now.
And it will position them at the correct spot.
As I showed earlier in the notes slide, this is actually
what allowed me to put myself back on the heading after the
user dismissed the speaker notes.
So it's great for focused management.
And again--
CHROMEVOX VOICE: Code highlighting enabled.
CHARLES L. CHEN: --really simple there.
The second parameter just controls whether or not to
automatically speak or if you want to
speak a custom message.
CHROMEVOX VOICE: ChromeVox APIs.
Handling user navigation.
Functions--
CHARLES L. CHEN: Now as I mentioned earlier, sometimes
your web application can do a much better job with
navigation than ChromeVox, because it knows its own
semantic structure.
In the case of the slides, when I'm not on a slide, all
the other content is actually hidden, so it's
invisible to ChromeVox.
So if I were to search for a next heading without any help
from the web app, I would actually fail.
Because there's only one heading here.
But since I give the web app the ability to respond first,
you as the web developer can actually say, wait.
I know how to deal with this next heading thing.
I'm just going to do it.
It's pretty simple.
All you have to do is listen for these ChromeVox events.
CHROMEVOX VOICE: Code highlighting enabled.
CHARLES L. CHEN: So you're just looking
for a cvox user event.
And then it has a detail object underneath it.
And if you look at its command, it tells you exactly
what the ChromeVox user is trying to do, and you can
respond to that.
And so I'm actually going to use that to navigate to my
next slide by going to the next heading.
Next heading.
CHROMEVOX VOICE: Handling user navigation.
Heading--
CHARLES L. CHEN: OK.
So as you saw there, it jumped me through that slide and took
me to the next slide.
In conclusion, what we covered in this talk was how you can
navigate through the DOM with different granularities and
how we're using the concept of granularities to support
special content, such as mathematics.
And we gave you an overview of how to do this with the
ChromeVox APIs.
One thing to note is this all works on Chrome.
And as I mentioned before, this works on web technology.
So this works on Chrome in any form.
This is also available on Android.
And it's actually a huge boost for developers, because now
you can develop on the desktop, test it out, and then
when you run it on Android you'll get the same effect.
And these APIs are also available everywhere.
In the audience, I actually see someone
from IDEAL Group there.
You can go ahead and wave.
So they're in our Sandbox, and they're demoing their
integration of their Epub reader with ChromeVox Android.
And they're taking advantage of ChromeVox's ability to
speak math to make their Epub reader even better.
We didn't cover in this talk is that we actually have
Braille support on Android.
And we're also working on it for Chrome.
There's a lot more complex and advanced navigation features,
such as working with tables sufficiently.
And then we also have HTML UI controls, such as date/time
and media widgets.
CHROMEVOX VOICE: Less than thank you.
CHARLES L. CHEN: The best way to catch all that extra
content is to visit our Sandbox.
And so please drop by our Sandbox and come
to our office hours.
You can find all of this information on chromevox.com.
And all of this code is open source.
And these slides will be available after I/O.
So with that, I see that we have about a
minute left for questions.
So any questions?
Please come to the mic.
Sure.
AUDIENCE: I have one maybe silly question.
But is it possible to set up a phonetic
dictionary that you could--
As we were watching this, the I/O or the "AP's" instead of
API, could I just contextually say, for this period, I want
you to, when you meet the word API, use the
sound API and not AP?
CHARLES L. CHEN: Yes.
So that is something that we definitely want to make it
easier and have it work better.
In general, that's usually an issue with the text-to-speech
engine, so you probably don't want to overcorrect for it.
That having been said, we do have the notion of being able
to tag HTML elements and nodes with hints.
It's in the API documentation.
But you can basically tell ChromeVox exactly how a node
should be spoken.
And this allows you to pull in additional semantic
information and speak it more intelligibly.
AUDIENCE: Would you be able to modify a dictionary.
The problem I've run into in this situation is you end up
annotate every single instance, when it would be
nice to just be able to have a dictionary of sounds,
especially if you're doing science content.
CHARLES L. CHEN: Yes.
So that's why we have the reading rules from Volker.
Volker, do you want to speak more to that?
VOLKER SORGE: OK.
Well, for the reading rules, you can
effectively annotate things.
You can effectively annotate single characters the way you
want them to be spoken.
Particularly for certain mathematical
symbols, that's important.
Obviously, in many ways, it is like a dictionary
that you can modify.
It would be ideal if then some of these things that you
modify on our end also would be spoken by the TDS engine,
which is obviously also a particular problem with
English TDS, which is not necessarily phonetic.
Yeah.
But you can do it.
AUDIENCE: OK.
Thank you.
CHARLES L. CHEN: And ma'am, you had a question?
AUDIENCE: [INAUDIBLE].
CHARLES L. CHEN: Similar.
OK.
I think we're actually running out of time.
So anyone else?
OK.
Well, thank you.
I hope you all enjoyed this talk.
Please catch us in a Sandbox.