Google I/O 2012 – Upgrading Your Web App to a Chrome App

Google I/O 2012 – Upgrading Your Web App to a Chrome App


PETE LEPAGE: All right,
welcome everybody. Thanks for joining me. I did hear a little rumor
earlier that the description for this was that you might
be coming up and showing off your apps. If you were expecting that,
not so much today. What did you guys think of
the keynote this morning? Liked it, yeah? Awesome Cirque du
Soleil thing? Cool, yeah? All right, sweet. I’m going to be talking about
how to take a web app and turn it into one of the new Chrome
packaged applications using the new technologies that we’ve
got available to us. Chrome packaged applications
do a lot of things that are really cool. And really allow us as
developers to build applications using the
technology that we know today already, that we know how to
use, divs and C S S and all that great JavaScript stuff. And build applications that feel
like they’re installed, that break out of the browser
so that they don’t have that browser bar cross the top. They don’t feel like that
experience of oh, I’ve got to open the browser and then I
got to go to this site. You click a button on the doc,
or you click something on the start menu, and the application
starts just as you’d expect it to. With an enhanced UI that allows
us to really be able to do things that we can’t
normally do in web applications. I want to be able to
open a window. I want to be able to move
it around or resize it. I want to be able to do things
that with web applications I can do today, but I might get
blocked because I’m not allowed to open new pop-up
windows and things like that. So an enhanced UI that really
lets us get beyond what we’re used to doing. Offline by default, apps
that just work. Today when an app gets installed
on your computer, you expect it to work. When an app get installed on
your phone, you start it, you expect it to work whether
you’ve got an internet connection or not. Chrome packaged applications
should work like that. Web applications should
work like that. And we need to get users
thinking about that, right? I got made fun of a little bit
when I used this reference, so pardon me, but when my mom
starts a web app, she goes to Gmail or wherever she’s going. If her computer’s not connected,
she doesn’t think that it’s going to
work if it’s not connected to the internet. So for her, we need
to really say hey, these apps work offline. And Chrome packaged applications
allow us to do that within this new model
that we’ve now got. And my battery is dead, so I
guess I’m going to have to move around. My name is Pete LePage, I’m a
Developer Advocate on the Chrome Team. And it’s my job to help folks
like you guys build web applications, build Chrome
packaged applications, and really take advantage of all the
cool stuff that you saw in the keynote this morning. And be able to get better access
to your customers, to your users, and to all the fun
stuff that Chrome really has to offer for you. You can find me on Google+. I’m also on Twitter, though I
don’t tweet very often, as well as my blog. And I’ve got some stuff
up on GitHub. So when I think about the legacy
packaged app, this is what a legacy packaged
app looks like. I’ve still got the address bar
up at the top, I still need to start it in the same way. In fact, let’s get out of here
and let’s have a look at a little packaged app. So we’re going to take a
look at this particular application. This is just a simple
RSS reader that I’ve gone and built. Because I wanted to see what
it was like to build an application and then convert it
to a packaged application. So you can see I’ve got a list
of different feeds available. I can go, I can scroll down, I
can go click on one of these. But I still have the address
bar up here, I can’t open new Windows. It’s not exactly the best
connection, it’s not exactly the best experience that I
really want to have as I’m reading through my RSS feeds
and all of that. So I chose this application in
particular because it does a couple of things really well. One, it’s a single-page
application. So it works really well,
there’s not a lot of navigation from page
to page to page. It should work offline. I should be able to take all of
that data that I’ve got and all of the stuff that I’m used
to using, and I should be able to just say all right, great,
I want to access all of that without having to do
anything else. So we’re going to walk
through what I went through to get there. So let’s go back ti the slides
for a sec and try that again. Hey, there we go, that looks
a little better. So when you think of a legacy
packaged app, you had a manifest file. How many people have built a
packaged app or a Chrome app in the past? All right, so few people,
about half the room. So you had a manifest file,
and that manifest file was really what told Chrome how your
apps should work and what it should start, where
it should go. And within that manifest, it had
effectively a link, or it said hey, when you start
I want you to go open this index file. And that index file might go off
and grab any resources it might need, any HTML,
or C S S. But all of that stuff fit into
as a package, into a zip file, that you uploaded to the
Chrome Web Store. And it could also sometimes
have a background page. And you might use that
background page to say go pull for data so that you
could pull data down and save it somewhere. You might use some
context menus. But all of that stuff, you’d
have to set up a loop. You’d have to either use a loop,
you’d have to use set interval, there were a whole
bunch of things that would cause some pain in the
butt sometimes. And could potentially, if you
didn’t write it very well or used some bad practices or worst
practices, if such a thing exists, could affect the
performance of Chrome for everything else. So one of the things that we
really wanted to address as we started making these
enhancements to Chrome packaged apps is
how we do that. How do we make it easier so
that the applications that you’re writing, it’s harder
to do the wrong thing. So let’s get started
and have a look at how I converted this. Now, I’m going to throw
up this warning. I’m just going to say
time out for a sec. This is a developer preview,
this is not something that you can go ship a production-level
app on. If you do, congratulations. You can’t get it in the
Chrome Web Store. But if you give it out to a
bunch of users, it probably will break at some point
in the future. So just that word of warning as
you’re playing with this. If you’re like hey, this worked
yesterday, but now that I got a Chrome update
it doesn’t work. Go have a look at the docs for
known issues in any updates. Because things are changing on
a regular basis, and we’re working to get a lot of
new great stuff added. And sometimes that means taking
your feedback and going oh, guess we didn’t think
about that one too well. I guess we better change that. So getting your feedback is
really important to us. We want to hear what you
have to say about these applications as you’re
building them. What are your experiences? How do we need to make these
things better so that you can build the type of applications
that you want to build? So with the new architecture,
it changes a little bit. Remember before we had our
manifest which would then kick-off an index file? In a new Chrome packaged
application, instead of kicking-off an index file,
the first thing that the application does is it kicks-off
a background script. So that background script, think
very similarly to if you’re writing a native
application for Windows or for Android or for any
other device. There’s some kind of like C#
file, or there’s some main file that might kick open other
windows and all that kind of stuff. It works in the same way. So that background script is
going to go, and it’s going to start running first thing. And when you want to start the
application, it then goes and opens your application
UI window. So it says, oh hey, the
user wants to start. I guess I should open this
window up, and it goes and opens that window. So the difference here, and
the really important thing here, is that background
script needs to listen for events. We’ll talk about
that in a sec. So the application that we used,
we didn’t use all of the technology that’s possibly
available to us, but we used a bunch. When we used the Chrome
experimental apps API– maybe it’s just standing
too far away. Maybe if I go over here. We used the chrome.storage.sync. I’m going to talk about
each of these in depth in a little bit. But chrome.storage.sync, how
many people used chrome.sync in Chrome when they used Chrome
today to sync all your passwords, your favorites,
all that kind of stuff? And, kind of cool,
chrome.storage.sync basically lets you take whatever you want
for your application, within a set of limits
obviously, and store that stuff up in the cloud. So that no matter which computer
I’m logged into, I have all of those settings
synced across all machines. So I can have maybe my
credentials, maybe a list of read items. All of that stuff I can keep
synced in the cloud. Chrome.storage.local which is
very similar, but it only is local to that specific
machine. We use Chrome alerts to notify
the user of a bunch of stuff. We use sandbox pages, and I’m
going to talk about Content Security Policy in a little
bit and why we’d use a sandbox page. And we used Angular.js. We used Angular.js because
Angular did something that made our lives a little
bit easier. How many people have heard of
Content Security Policy? Yay, OK, only a couple hands. We’re going to go into
more depth on this. This is something that’s really
important, but it could change the way we think
about a lot of stuff. And it’s, like I said, it’s
really important and it will make the web a lot safer. Nice big eye chart. This is how the app is
kind of laid out. So you can see right there in
the center of the app is that background page. And that background page goes
and does all of the stuff we need to do. And I promise, we will get into
real code here shortly. I think it’s like one slide
or two slides away. So we’ve got that background
page, and it goes off and kicks-off the app page there
at the very bottom. It goes over and it gets access
to data in different data places. And it goes up to the cloud
and it asks for feeds. So the first thing we need to
do in our application is we need to update the manifest. The manifest for a new packaged
app has changed a little bit, and I want
to highlight a couple of the changes. So the first thing that changes
is we need to add a manifest version 2. Manifest version 2 tells Chrome,
hey, this is a new Chrome packaged app. It also turns on Content
Security Policy. Second thing, we want to add
offline true, because our apps are designed to work offline. Everything that we have we need
for our application is sitting there in our zip file in
our package that we zipped up and uploaded and
is good to go. The next thing is we
need to add the app background scripts. If you remember before in V1
apps, that was where we put our index file. We said, hey, this
is my index file. And then finally, we need to
add a couple of specific permissions. We need to add the app window
permission which says hey, we want to be able to open windows,
we need to be able to manipulate windows. We want to do all that stuff. And then we need experimental. Now, we are only going to need
experimental while we’re in an experimental stage, so
that will go away sometime in the future. And that right now is one of the
things that will prevent your app from getting uploaded
to the Chrome Web Store. So if you go and you’re like,
hey, I got this great app and I want to get it in,
and you’re like why won’t it upload? Well, that’s a big part
of the reason. So let’s go and actually
do that. So I have here my text editor. And don’t worry, we got some
nice decent size fonts here. And instead of doing it in
there, I’m going to do it in my Updated, and I’m going
to go grab my manifest. All right, so we need to
add a couple of things. So we need to add our manifest
version, and we want to set that guy at two, right? We want to add offline enabled,
and we want to set that to true. Then, remember we said we had
to change from the index to instead use our background
page? So I’m going to say background,
and I’m going to go here and say scripts, and
turn that into an array, because we can have multiple
background scripts. And I’m just going to say
background.js, and I’m going to put that in my js folder. All right, two other things
we need to do. Run permissions, and appWindow,
and experimental. All right, so we’ve done
all the things we needed to do here. So we’ve got our manifest
set to go. We can’t actually go hit run
yet, because we don’t have our background page. So let’s have a look at what
is in our background page. So in our background page we’re
going to put primarily just one chunk of
code for now. And that’s the listen for the
application start event. So instead of doing loops and
all kinds of other stuff like we did before in the legacy
packaged apps, everything is event-driven, event-based. So we want to say right there
in the top bit of our app, Chrome experimental app
unlaunched, add listener. So we want to say we want
to listen for an event. And we then say all right, when
that event fires we want to start and create
a new window. And the window we want to create
is the index HTML. Now, I can also add a couple
additional properties. So I can say I want that window
to open up at 1024 by 768, I wanted it to open at 100
pixels over and 100 pixels down, and type shell. All right, we’re just going
to cheat a little bit. We’re going to copy this and new
file, paste that guy in, background.js. So we’ve got our background
page in, so it’s there. Now when the app starts, we’re
going to be good to go. There’s a couple other events
that we can listen for, like the uninstalled and an
on suspend event. We’re not going to worry about
those right now, because really the only thing we want to
do right now when we start is the on start. Couple of things we need to
do just in preparation. In the future we probably
won’t have to do this, but for now we do. This stuff is only available
in Chrome Canary. There’s a reason for that, kind
of fun, kind of a little bit on the edge. Chrome Canary’s where
you can always get the latest and greatest. It will be in dev
channel soon. Now the great thing about
running it in Chrome Canary is that you can run Chrome Canary
and Chrome Stable or Chrome Beta or Chrome Dev
side by side. So that way if you’re ever like
OK, well, I want to go try something and see how it
works and I still need to actually be able to browse and
do my real stuff, you can have those both side by side. So Chrome Canary, and then we
need to just go add our app, just like we did with the
legacy packaged app. So the first thing I’m
going to do, let’s go over to Chrome Canary. And I’m going to close this guy
out, I’m going to go to Tools, and Extensions. So I’ve already checked the
developer mode, so I’m going to go and load an unpacked
extension. So I’m going to grab this, click
Select, a-ha, all right, dictionary keys must be
quoted, so line 16. You know that pink thing that’s
right there might have given it away when I was
doing this early. Try that again. All right, so now if I
go over here, you’ll notice I’ve got my legacy. We’ve got my final, so we’ll see
what that looks like in a sec, but I’ve got the updated. One thing you’ll notice, the
difference between the legacy and the updated, the legacy is
kind of gray there because I don’t have an internet
connection right now. By putting that offline enabled
there, it tells the app hey, this app
works offline. And as we go through and have
a look at why it works offline, you’ll get into this
a little bit deeper. But let’s go and
start our app. Hmm, OK, it’s started, but it
doesn’t look very good. I would expect to see some
numbers there, I’d expect to see some data. At least we have an app running,
our window opened. We’ve got a sad panda, we
can deal with sad panda. All right, so let’s see that in
action, we already saw it. What happened there? We actually got hit by something
called Content Security Policy there. I asked how many people
have heard about Content Security Policy. It’s a new thing that’s coming,
and it’s going to make the web a lot safer. But it also makes things a
little bit different for us as developers, because we have
to approach things in a different way. I kind of like to use a little
bit of an analogy of it, and talk about it as when you
take the kids trick or treating at Halloween. They go out to all these
strangers’ houses and the strangers give them candy. And you get home, and as
parents, the parents sort through the candy and say you
can have this, you can’t have this, you can have this. As a kid, you’re like I want
all of it, it’s all good. Like, you want all that
candy, but some of it’s potentially dangerous. The web is very similar. When we say hey, you can take
anything you want, you might get good stuff, right? You might get great stuff, you
might get great data feeds, you might get whatever
you want. But somebody out there might be
malicious and say oh, I’m going to give you some bad
stuff, and you’re going to get something like a cross-site
scripting vulnerability. Well, Content Security Policy
basically says on the web you are allowed to get content, data
source, whatever, from these places, but
not from these. So just like when your parents
came in at Halloween and said you can have this candy but you
can’t have this, Content Security Policy does
that same thing. It says this is safe,
this is not. Now with Chrome packaged apps,
we said you know what, let’s make these apps as
safe as we can. So we put a relatively strict
set of rules on that. So let’s talk about a couple
of the things that are potentially dangerous, why
we block them, and what’s going on. So any code that comes from
outside of your control, so that’s not delivered in the
package of your application, is going to be blocked. That means if you try and go
get Google Analytics, the ga.js kind of code, that’s
going to be blocked. Sure, you get it from
Google Analytics. We’re probably not evil, at
least I hope we’re not. Well, we’ve got this
thing that says don’t be evil, right? So that’s OK, but we don’t know
where you’re going to go get all this stuff from. So we say if it’s not your
package, you can’t have it. Because you might go and get
something from somebody else’s source, maybe somebody said
oh hey, I’ll host Google Analytics code for you. And all a sudden it’s not
actually that code anymore, and they’re doing something
malicious with it. So if it’s code from outside of
your control, you can’t put it in the app. Second thing, we block
inline scripts, including JavaScript URLs. That one kind of sucks, right? We’re kind of used to
sometimes doing that kind of stuff. Now, it’s not exactly a best
practice for doing that, but inline scripts– the problem
with inline scripts is, so we’re looking through this HTML,
and we come across a script block. Well, if we come across a script
block, how do we know that you as the developer
actually put that in there versus somebody injecting that
in via some kind of cross-site scripting attack, or
something else? So anything that could get
injected into the HTML, nope, sorry, we’re not going to let
that happen because it could potentially allow that
cross-site scripting. This one I think should be
pretty obvious why we don’t let you have eval. Eval is kind of evil, it’s
one letter away. So unsafe code execution like
eval, because you could basically take any text, run it
through eval, turn it into some nice, cool, nasty
script, not so good. Pretty much every browser today
supports JSON.parse and JSON.stringify. String/file. So realistically, the need for
eval is pretty limited. There are a few places where
eval is useful and where eval is good. Safe, good, protecting your
users, protecting your customers, protecting your
data, potentially evil. Hmm, I usually like the
safe, good better. So let’s have a look at a
practical example, like a very specific example here. So this is in the HTML of my
application, I’ve got a function that says callme and
it prints out a little line. And I’ve got a button, and the
button has an onclick directly on it that calls the function,
and I’ve got some text in there. So that’s not going
to work, right? We’ve got both an inline script
block, and we’ve got inline script in our
button as well– not going to happen. So here’s the better
way to do it. It’s a couple more lines of
code, but it’s the better practice to do it. First thing we do, we’ve got our
script block that links to our file, and then we put
our button there that says hey, call me. It’s got an ID on the button so
that we can get access to it a little bit later. And then we have our
function in the JavaScript that says callme. And we add an event listener
to say hey, go grab that callme button and add a listen
so that when the user clicks on it maybe they call. Sorry, bad pun, bad joke, I like
that song, I admit it. I’ll go away in shame now. So this is the better
way to do it. There’s a bunch of really great
content out there that talks about CSP. I’ve got a link to it at the end
of the slides, it’s really worth having a look at. Converting from inline script
blocks and that kind of stuff, not an impossible thing to do. It takes a little bit of work
and a little bit of rethinking on our part, but something
really important that we should do. So one of the things I’m going
to do, let’s actually get out of here for a sec. And before we go over there,
let’s tab over here. So one of the reasons why I
chose to use this app and why I chose to use Angular, is
Angular actually has some CSP ability to deal with it right
inside so that I don’t have to go and deal with all
the craziness. I can actually just go ng-csp. And that now, if I did
everything right, I’m going to close this guy, open this up,
and I didn’t do it right. All right, I’m going to cheat
one sec, I’m going to have a look at my file over here. Ng-csp, that was the
right thing to do? Oh, yeah, reloading helps. So over here, go reload my
app, and sure enough, it doesn’t work again. I can come back to that, because
I’ve actually got something else I’m going to
do in my next step here. So one of the other things that
is really important and really useful to do in moving
your app to a packaged app, is taking that shared and common
functionality, pulling it out of your JavaScript places where
it’s going to get used in multiple places,
and putting it into the same place. So with the RSS reader
application we’ve got, it goes up and it pulls for data, and
then it pulls that down and it goes and puts it into
a data store. So for something like this, we
want to take that and put that into the background page. So that we take all that shared
code that’s all over the place, maybe a little bit
spaghetti-like, and try and really reduce some of the
work that’s going on. One of the ways that
you can do that and that’s really useful– we’ll dive into the
chrome.storage API in a sec– but in my application I could
take this chrome.storage listener and I can say hey,
anytime anything changed I want you to go listen
for this. And I want to update all of the
rest of the page so that oh hey, I just got new feeds,
let’s go update what’s displayed to the user. So I was talking a little bit
about the package, making stuff work offline. And making applications work
offline, we can do it on the web today, but it is a small
pain in the bum to put it mildly, right? Like, there’s AppCache, then
you’ve got to deal with well, where are you going to put it? Are you going to put it in an
index db, you going to put it in local storage, are you
going to put it– where are you going to put it? And well, typically as web
developers we say hey, let’s go get data from the cloud and
then display it on screen. Oh well, maybe we should just
store it locally, too. So when you start to think about
your applications and how they should work offline, we
want to think about them in a little bit of a
different way. So we’ve got our packaged app,
and our packaged app should talk to a local data
store first. So some kind of local
data storage. That way, if I have no network
connection I’m always going to be able to pull data in. I start my app, hey look,
there’s data. It may be stale and old data,
but at least I’ve got something, right? Like, you go to Goggle+, you go
to any other site, you want to see something when
the app starts. Now, it’d be really kick butt if
we could also store all of that data in the cloud
so that it was synced across all of my computers. So that I didn’t have to go oh,
hey, well I haven’t run this app in a while on this
computer, so I guess I don’t have this data. I want all the stuff synced
across the cloud so that I open my Chromebook, great,
I’ve got all that data. I open my iPad with Chrome on
it, I’ve got all that data. I’ve got, open whatever device
I’ve got, I’ve got all of that stuff synced across the cloud. And there’s a great new Chrome
API that’s going to help me do that. And then finally, from our local
data store, or from our background page, we want to go
and have that talk to the backend services for
our application. So our packaged app, our UI, is
never talking to any kind of application server-side
stuff. All of that is happening on
a separate business layer. When you think about, if you’ve
taken computer science classes and you separate out,
hey, here’s my business layer, here’s my display layer,
here’s all this stuff. You’re separating all those out
and that’s what we really want to see in these
packaged apps. So that your app talks to
the data store, pulls everything in there. And then the background page or
any of those other pieces then go and pull stuff
in so that we can deal with those pieces. So we have this new set of
chrome.storage APIs. They give you all the power of
Google’s Chrome Sync stuff without having to go deal with
oh, well, I got to go set up a bunch of servers. I got to figure out how
to do data syncing. I got to figure out how to
do all these things. Now it’s not meant for
you to store tons and tons and tons of data. That’s Google Drive, and we do
have some easy abilities for you to get into that. They’re not quite there yet,
we’re not going to talk about those in today’s session. But to be able to store user
settings, not necessarily login information, but
application settings, or little bits of data like key
value pairs is exactly what we want to use this chrome.storage
API. So there’s a couple of things
we need to do it in order to use it. One, we need to turn on the
storage permission, because it needs a permission. And then there’s two things we
can do, we can get and we could save– or I guess that’s
technically set. There are some other APIs, but
these are the key things I want to show you here. So if I want to save something,
I use this set. Let me highlight this out
here for a sec, and we send it in object. That object is just a name value
pair, or a JSON Object. So I’ve got hey, here’s all of
the Chromium articles that I’ve got that I want to
save, and I give it that list of items. And then I’ve got a call back
that’s used to say all right, everything’s saved, you’re good
to go, all hunky dory. To get that stuff out of the
back side, we use the chrome.storage.sync.get, and we
just ask for what we want and we give it a call
back again. And so Chrome says OK,
yep, you want that? Sure, no problem, I’ll give
that to you in a sec. Goes off, gets it, and pulls
it down and gives it to you via that callback. So let’s actually go take a look
at the code we’ve got. And trying to do the two things
that I just talked about up on stage would have
been a little messy because it changes a lot of stuff
in this application. So I want to show you the things
that we did in order to get that to work. So our background page before,
you remember, was just that start for our application. So we’ve got that still in here,
so we add our Chrome Experimental app launched, and
we open up our window. And we’ve moved a lot of the
code that our application is using out into here. So we’ve got a factor here
that’s going to go and do our feed fetching. So all of our feed fetching, all
of our feed syncing, all of that is done here in
our background page. So we’ve got our factory to
get our feeds, we’ve got a factory again here where we’re
refreshing things, and then we’ve got some angular stuff as
well down here, just sort of angular filtering stuff. We’ve also gone and created
a store module. So Angular allows you to have
these concepts of modules. So we’ve got in here our store
module, we create our factory, and we want to say hey, we’ve
got our state store and our content store. As we’re working on this, we
sort of said OK, we’re storing large amounts of data. How do we do that in
a really good way? How do we take all of that
information and put it in the user’s hands without sending
lots of data up to the cloud, without overloading all the
user’s synced storage space and complexities? Said OK, well, what if we
separate out the blog feed, each RSS poster, each RSS
item, from its state? So we said we want to sync all
of the state, whether it’s been read or not, and whether
it’s been starred or not, and we’re going to store that
up in the cloud. Because that’s, what,
two bits? It’s not even a byte for
that matter, because it’s just like a Boolean. And then we store all of the
information about the feeds on the user’s local computer,
because we can always go get those later, those
are easy to get. So we’ve separated those two
things in our data storage. And then when we go to actually
get these things, just sort of scroll down here. So we go and get our feeds from
content storage, which Angular then has a way to say
hey, if there’s everything in there, we want to go and do
a forEach on each of them. So we’re going to go and iterate
through each item and go and add them to the
user’s display. So let’s go and add this guy. So I’m going to load our
unpacked extension, and we’ll grab number three that
we’ve refactored. And sure enough, now we
don’t have anything. But that’s OK right now,
because I don’t have us plugged into the network
right yet. So now we’ve got all
of our data. Everything works right, but
we’re trying to pull everything from our
local machine, we don’t have anything. So let’s try it again. I’m going to close the window. Actually, I’m going to
join a network first. I’m going to be a little bit
brave, I’m going to try it on wireless first. Think we can get it
working today? All right, so close
this window. And so it’s fair enough,
now we’ve got our data. So we’ve got everything in
there, and I’m going to go turn Wi-Fi off again. So now because I’ve turned the
Wi-Fi off, if we try and go get everything from the
server it should work. So close this guy out, start it
again, refactored, and sure enough we have everything
back again. Now if I were to go and try this
on another computer that I’m signed into, all of the
things that I’ve read are going to be synced across
the different computers. Now it’s going to have to go and
pull that data down on the second computer, but the key
point being it knows what I’ve read, knows what I’ve starred,
it knows what I like. So I’m able to store specific
sets of information about what I’m really interested in, or how
I want to go and do these things, across different
places. Keeping the application up to
date is also really useful. It would be nice if when I
first started the app it didn’t have to go and download
all the stuff and say all right that first time, but
instead it just always stayed up to date. So that the first time I started
it, or that first time I opened it after not using it
for two days, all of my data’s there, right? You go to Google+, wouldn’t it
be nice if that first time it loaded it was all fresh data
instead of going oh, now I got to wait for it to load, do ta
do ta do, OK, now I can see what I want. We want that ability so that
when users start the application, users want
that fast, fast. They want– there’s something else, like a
different app that’s just as good but theirs is faster,
they’re going to go use the faster app. They’re going to use somebody
else’s app. So we want to make sure your
apps are nice and snappy, your apps are nice and fast. So there’s this new
Chrome.alarms API, and it works very similarly to set
time out or set interval. It’s got three– I guess it’s got three, I
thought it had four– it’s got three different
settings on it. One, Delay, so you can say hey,
from the time you fire this event, I want you to wait
five minutes and then fire. It’s got a Period, which is very
similar to set interval, and it’s going to fire
every X minutes. And then finally there’s a
When that’s like for a specific time. Now for alarms, to use that,
again we need to turn on a specific permission. So we’re going to say hey, we
need that alarms permission. And then we go and
create an alarm. We give it a name, and we give
it a particular property. So whether we want it to fire
in a period of minutes, whether we want to fire
it in a delay, or a when, or whatever. So in this particular case,
we’re going to use a period in five minutes, which is
going to fire the event every five minutes. Now, remember one of the things
that I said earlier was that it’s really important that
these apps really work seamlessly and not cause
a lot of headache or anything like that. So we don’t want to have
functions that are sitting there looping. We want everything to
be event-based. So because this is an event,
we need to create an add event listener. So we’re going to add
our event listener. So I’m going to go and I’m just
going to– in fact, we’ll pop this into our application. And I’m going to
put this into– not that background– and I’m just going to close a
couple of these so that we can actually see where we are. I’ve put in a place where I want
to put my background, so I’m going to add my listener. Let’s make that a
little prettier. And the other thing we need
to do is start our alarm. Now I’ve already added the
alarms permission, so we don’t need to go add that. Pop that in, now the app will
stay up to date and everything will fire every five minutes. Now, I probably should have
picked a blog feed that was posting more than every five
minutes, or probably posting once a day right now because
of I/O. But you can imagine for something like this where
you’ve got something that you want to keep up to date, maybe
a friend’s feed, or maybe something from Twitter, or any
other API that’s changing on a regular basis, you want that
to fire much more quickly. So there’s a bunch of other new
functionality in APIs that are available to us that
are pretty slick. Some of them didn’t really fit
into the app all that well. Because of the way the app was
written, they didn’t really fit all that well. They were one of those things
where it’s like ah, OK, well this wasn’t really particularly
needed. But I still thought they were
really cool and definitely worth talking about. There’s a new Identity API
that’s available that allows you to have your application
automatically log into Google services. So the user says hey, I want to
log in to this particular Google service. This is really for making it
easy so that you can get things up to drive, or if you
want to access any of the other APIs that Google
has to offer. So there’s a couple of things
that we need do here in order to use it. First thing you need to do, add
that identity permission. And then we create a new block
within the manifest file, and we say OAuth 2.0 so it uses
the OAuth 2.0 protocol, I guess it is. And we go in and we provide
a client ID. So you get your client ID
from the dev console, so code.google.com/API/console. You get your client ID from
there, and then you specify the scopes that you want
to get access to. Much like you do if you’re
writing any kind of other web app that uses OAuth. We take all that complexity, all
that pain in the butt– if you’ve ever done OAuth 2.0,
it’s definitely at least easier than OAuth 1.0, but it’s
still not exactly the most fun thing to do. And we simplify it for
you all in here. So we’ll ask the user to sign
in, yep, great, here you go. And then you don’t ever have
to worry about it again, because all those requests that
you make will be done with the right set
of permissions. And then there’s also when
you need to go get the authentication token, there’s
just a simple API that you call and say hey, go
get me that token. All right, we’re good to go,
we can start doing things. One of the ways that I wanted
to use this and see myself using this for in the future,
is if you wanted to build an offline RSS reader that actually
grabs the user’s feed from Google Reader, you could
use exactly this API to say all right, let’s go authenticate
the user. Now we can go and get their feed
information, figure out what they’re reading and
pull it in that way. So that way instead of having to
go deal with anything else, we’re golden. We can just, sweet, don’t have
to write anything crazy in order to do that. There’s a bunch of other stuff
that I think is pretty slick. Context menus, like real apps. If I’ve got an app that’s
installed on my computer, I expect to be able to right-click
on it and pull up a context menu. Chrome apps have the ability
to say hey, I want a context menu. So through Chrome context
menus create, you can go and do that. All of these– don’t worry about writing any
of these down if you can’t really read it all that well. You can go check the slides
later, or have a look at some of the docs– create windows. Apps should be able to create
as many windows as often as they want without being spammy
or annoying, but real apps can do that. We’re kind of prevented from
doing that on the web. For a good reason most
of the time. But we just say create a
window, provide a URL– that URL is a local URL. We can’t say open a URL to HTTP
whack whack Google, or whack whack whatever,
it has to be a file within our package. We’ve got great stuff for doing
window manipulation. So I can go and set
focus on a window. I could say this window should
be in focus right now, or minimize and maximize windows. Just like you can with regular
applications that the user has installed. They’re used to having app do
that, like hey, this app, I want you to go away because
I’m not really using you right now. Great, done. We can have them restore, move
and resize, just like we can with regular installed
applications. One of the ones that
I think is kind of cool, text to speech. So you can have your apps
start talking to you. There’s even one that’ll listen
for what you say, so there’s a speech recognition. Hmm, speech recognition plus a
little text speech, you could start writing your
own kind of fun– anyway, you can figure out where
we’re going on that one, or where I think you should
go on that one. There’s a couple other API
changes that I want to call out because I think they’re
pretty important. Links. When we’re used to writing web
apps, we put links in our apps, right? Like, you’ve got a link that
goes to here, you’ve got a link that goes to there. Links will open in a new Chrome
window if they go to somewhere external. So keep that in mind. That like hey, if you put a
link to HTTP whack whack Google.com, it’s going to go and
open up a browser window. It’s not going to
open up within your application window. So links to outside places will
open in a new window. By default, this one threw me
when I first did it, because I was like, why can’t
I select anything? I’m trying select something. Think about most applications
that you have. You can’t go and select most
of the text on there unless it’s a text box. So just like an installed
application, you can’t select the text in one of these
applications unless you specifically say this region,
this block here, the C S S div span, whatever, is selectable. So by default, we say
user select is none. We can’t put iframes in there,
we got to use something called the browser tag instead. Again, that’s a security
thing. Think about hey, we’ve got this
app, this great app, and we let you put an iframe in. Or you’re rendering content from
somewhere else and they put an iframe in. All of a sudden you’ve just
opened this gigantic potential security vulnerability, because
other people could start putting anything they want
within your application. So we make it very explicit
what you can and can’t put into those. You could create some sandboxed
iframes, and the browser tag is a
sandbox thing. If you didn’t make it to Eric
and Mehi’s session earlier, they showed some specific
demos around that. Kind of neat stuff. Local storage and Web SQL
are also turned off. Local storage is turned
off primarily for performance reasons. It’s synchronous, so hey,
go put something into the data storage. OK, please wait while
I do that. Applications should be fast. Having synchronous things
happening is not exactly going to do that. We’ve also turned off Web SQL. It is a deprecated API. Will it ever go away
from the web? Probably not, but it’s
not getting the attention it deserves. So instead, use something like
index db, which has a pretty strong following right now and
it’s got good browser support. The FileSystem API is
another great one. It allows you to store big
files on the user’s file system in a sandboxed
environment so you can’t exactly go read their resume and
their user documents file or something like that. Or use the storage API that I
talked about earlier, so that you can go in and say hey, I
want to store something on the user’s computer, I want it
synced up into the cloud, or maybe I just want it locally
in this one specific place. Most plug-ins and a number of
the Chrome extension things are disabled. So you can’t go put some kind
of plug-in in your app, we stopped those from happening. We think the web can be built
without any plug-ins. You saw this morning in the
keynote, the Cirque du Soleil thing, there were no
plug-ins there. That was all HTML, C S S and a
bunch of divs and some images. So all that stuff can be done
without plug-ins, so let’s start doing that. And finally– I know I’m guilty of it myself
sometime, you put in an alert or something like that
so you can do debugging modal dialogs. Users don’t want
modal dialogs. So instead, use custom light
boxes, use other things so that the app can keep running. Because the one key thing
about modal dialogues is they’re not just a modal for
what the user’s doing, but they also stop the
app from running. So any of the JavaScript is just
sitting there going do da do da do, we’re not
doing anything. I could stand up here for three
minutes and not say anything, and it’s
just as boring. So you want your app
to keep running. So what’s next? You could start using this and
start playing with this today to really build apps that break
out of the browser. I go back to those first
four points. They break out of the browser so
they don’t have the address bar, so they don’t look like a
browser-based application. Takes that power that we think
the web has, and really allows it to break out of there and
become a much bigger platform. The enhanced UI so that you can
control how applications look, how they feel, how they
open and close windows. They feel like they’re
installed, that they work offline by default. This is the one I think I’m most
excited about, because it means that I can write stuff
that works offline and that people expect to work offline. I’m going to say, I’m going to
use it again, and some people will make fun of me. My mom doesn’t expect web
apps to work offline. She’s going to expect these to
work offline, so we got to start building them this way. And finally, really takes
advantage of the native capabilities through new APIs. I didn’t get into it at all in
this session, but you should drop by the Chrome
booth afterwards. We actually have taken one of
these new packaged apps, used the Bluetooth API through this
packaged app, and we’re controlling a LEGO Mindstorm
robot with it. So you’ve got access to
Bluetooth, USB, TCP, UDP. You’ve got great access to truly
the device that these applications are running on. But most importantly, you can
start testing this today. Go install the Chrome Canary
build and start playing, because there’s a lot of
great stuff there. There’s a bunch of really good
resources if you’re looking to get started in this. The Chrome packaged apps
documentation, the URLs there, these slides will go up
online momentarily. But if you go to
developers.google.com/chrome, all of that stuff will
be linked from there. If you’ve got questions, you’re
working on something and you’re like why isn’t
this working? Send an email to the
Chromium-Apps Mailing List. We all have a whole bunch of
great sample applications, so you can see how some of these
applications were built. And finally, the last one that
I put up on there because I thought it was really useful. Mike West, who’s at the back
of the room, wrote a wonderfully fantastic
article that is an introduction to CSP. I gave you sort of a taste of
it today, but he goes into a lot more depth, additional
things it’s useful for. And if you’re going to use it
in a website, how you can go and adjust some of the different
permissions to restrict or loosen things
for websites. You can’t change them in a
Chrome packaged app, but you can change them on the web. With that, I want to say thank
you guys very much for coming and sticking with me. I hope this was somewhat
interesting for you. The link to the slides is up
there, you could see it, goo.gl/5krvb. The slides are up there now. I’ll say thank you,
I’ll open it up to any of your questions. AUDIENCE: So how would I put
Analytics into an app? PETE LEPAGE: That’s
a great question. So the question, I guess I
don’t need to repeat them because we have microphones. We are working on an Analytics
API that will allow you to go and do that so that you can
just say hey, here’s my Analytics UA string, and here’s
the things I want to [? apply. ?] We’re not ready with it yet, but
it will be coming at some point in the near future. AUDIENCE: Could I copy
the Analytics js files and package them? PETE LEPAGE: So the question
was, can I copy the Analytics js files and include them
in your package? You could try. My guess is it probably
won’t work, I haven’t tried it myself. It uses cookies, so
the answer is no. There you go. AUDIENCE: Is this stuff going
to work on Chrome for Android and iOS? PETE LEPAGE: So Chrome for
Android, Chrome for iOS, it’s something we’re definitely
thinking about. I think as Sundar said this
morning, it’s something we want to bring there, it’s
not there today. I want it just as soon as you
guys do, because hey, if I can write an app and have it work
everywhere, I’m a happy guy. AUDIENCE: When can I write
my Chrome app in Dart? PETE LEPAGE: When can you write
your Chrome app in Dart? I believe you can write your
Chrome app in Dart today. I’ll give you two answers. One, you can write it in Dart
today, compile it down to JavaScript, done, you
can publish today. In Dart, I’m not sure how close
the Dartium browser is staying to the Chrome
dev channel. So whenever those guys are close
to whatever we have in dev today is then. AUDIENCE: The Manifest
by JSON had a JavaScript function call? PETE LEPAGE: Yes, so that’s
a good question. I don’t have an answer
to that. Do either of you guys
know offhand? MALE SPEAKER: Right now
they [INAUDIBLE]. PETE LEPAGE: So right now
JavaScript only, but it is something that potentially
is coming? Is– yeah, well. So Mehi is one of
the developers. MEHI: Hi, I’m one of the
engineers on Chrome apps. So these APIs have a language
agnostic binding system, and the goal is to expose them
to Dart Native Client and JavaScript. Right now only the JavaScript
part is implemented, but coming soon those other two. PETE LEPAGE: Cool. Any other questions? All right, well that’s
the way to finish. I’m sorry, I’m going to let
you out a minute and 20 seconds early, I hope
you don’t mind. Thanks guys, have a great
day, have a great I/O.

Danny Hutson

1 thought on “Google I/O 2012 – Upgrading Your Web App to a Chrome App

  1. not neessarily. Most of the things you can do on the server side, can be done on the client side as well. LocalStorage and IndexDB allow you to store data, the File api allows you to read files from a user's filesystem,… And when you come back online, you sync the data that you have locally with your online database.

Leave a Reply

Your email address will not be published. Required fields are marked *