Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Applause ]
>> BRIAN WEINSTEIN:
Hi, everyone.
I'm Brian Weinstein.
I'm a Safari and WebKit engineer
and here to talk to you guys
about What's New In
Safari Extensibility.
Today we are announcing a few
new ways you can extend Safari.
You can write content
blockers for iOS and OS X.
There are changes to the
Safari Extensions Gallery.
And a new type of
app extension for you
to put your content directly
in Safari's Shared Links.
Let's get started and
jump right into talking
about content blockers.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Let's start with the
big question here:
What are content blockers?
Content blockers identify
subsets of content or resources
on a page to not
show or even load.
I'm sure you can all imagine
content you might want to block
when browsing the Web.
There are two main ways you
can block content using a
content blocker.
You can hide elements on a
page or you can block resources
from loading altogether.
You have been able
to do this for awhile
with Safari extensions on OS
X, but today we are bringing
that capability to iOS.
Apps will tell Safari the
content they want to block ahead
of time instead of
Safari consulting
with the app during the
actual loading process.
This new model is very
fast and efficient
because Safari doesn't
have to consult
with the app during loading,
and the content blockers
are compiled into byte code
that can be evaluated
very efficiently.
Additionally this new model is
great for your user's privacy
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Additionally this new model is
great for your user's privacy
because content blockers have
no knowledge of the browsing
that its users are doing.
And to get started creating a
content blocker you will create
an app extension on iOS
that will return a list,
a JSON string containing
the list
of rules describing the
content that you want to block.
So there's this website I go to
regularly where the author talks
about different golf
courses he's played
and posts some beautiful
pictures.
However, there are a few things
that annoy me about this site.
I would like to write
a content blocker
to block the content
that bothered me.
The most obvious
annoyance is this list
of click bait links on the left.
They even follow me around
on the page when I scroll.
So let's write a rule that
will hide this element.
So we get started by seeing
which element we should hide.
Looking at web inspector we see
there's a div with ID leaks.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Looking at web inspector we see
there's a div with ID leaks.
When that is selected
in web inspector,
we actually get an overlay
on the device itself showing
that this is the correct
element that we want to hide.
So now that we know the
element we want to hide,
let's write a rule to do it.
So each rule, each content
blocking rule is a JSON object
containing action and
trigger dictionaries.
The action tells Safari what to
do when the trigger is matched
and the trigger tells Safari
when it should perform
the corresponding action.
So let's start by taking a
look at our action dictionary
to hide the element,
to hide this element.
Our action has the
type CSS display none
which means we are applying
the display none style
to an element on the page.
When the action type
is CSS display none,
a selector is required
in the action dictionary.
All selectors that are
supported by Safari
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
All selectors that are
supported by Safari
and WebKit are supported
by content blockers.
So for this example we want
to block the content
with the ID Links.
Now we define when we want
this action to take place.
The trigger dictionary
is used for that.
Since Links is a pretty generic
selector and could be used
for real content on other pages,
I only want this rule to apply
when the user is on a page
on bigbearsgolfblog.com.
If I wanted this rule to
apply when the user was
on any site except
bigbearsgolfblog.com,
I would just replace the if
domain key with unless domain
and keep the value the same.
And I would like this action to
apply when loading any resource.
Once again, as long as I'm
on bigbearsgolfblog.com,
so I set my URL filter which is
a regular expression that is run
against the URL of every
resource being loaded
to match all URLs.
And we'll talk a little more
about URL filter
in a later example.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
about URL filter
in a later example.
So let's see what this rule
looks like all together.
We have our action
type, CSS display none,
which says that we
are hiding an element.
Our selector which describes
the element we are hiding.
And then in our trigger,
we specify which domains we
want this style to apply to.
And which resources we want
to apply it to when loading.
So when the content
blocker is applied,
here's what the page looks like.
The list of links is
gone and I can just focus
on the content that
interests me.
However, when looking
at Web inspector,
I found another annoyance
on the page.
If you look at the
resources on this page,
you can see that there's a
script loaded called Tracking
script.JS from example.com and
this script actually tracks me
across various pages that I
visit and can build up a profile
about me from my
browsing history.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
about me from my
browsing history.
When I look in the console
it also helpfully warns me
that I'm being tracked.
Thanks, Tracking script.
Let's block this script
from loading altogether.
We start by defining the
action for this rule.
The action type is block, which
means we will block the load
of any resource matching
the corresponding trigger.
So let's take a look
at that trigger.
The trigger defines when
the action should fire.
So in this case we've
defined a URL filter,
a resource type,
and a load type.
The trigger will file when
all three, the URL filter,
the resource type, and
the load type all match.
Let's start by talking
about the URL filter.
It is a regular expression
that is run against each URL
that is being requested.
So in this case it
will match any URLs
that contain the string
Tracking underscore script.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that contain the string
Tracking underscore script.
This will match
example.com/Tracking script.js.
The rest of the components
of the trigger increase the
specificity of the trigger
so we don't block more
content than we want to.
The first way we do this
is by specifying a list
of resource types
to match against.
In this case we only want to
block the loading of scripts.
So we pass script as the one
resource type we want to match.
Lastly, we specify a
load type of third-party.
There are two possible
values for load type.
There's first party
and third party.
A load is considered
first party when it comes
from the same scheme, domain,
and port as the main
resource on the page.
In our case, we only
want to block the loading
of tracking script when
it is a third-party load.
So this means if the
user was on example.com,
this script would still
load successfully.
So let's see what the rule
looks like all put together.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So let's see what the rule
looks like all put together.
And when we reload the page
with this content blocking rule,
you can see that we are not
loading Tracking script.js
at all and there are no
warnings in the console
that we're being tracked.
Great!
[ Applause ]
So your content blockers
will just be JSON arrays
of these rules.
Now that you've described the
content that you want to block,
the next step is to get
your content blocker
on an iOS device.
As I mentioned before, content
blockers on iOS are loaded
from an app extension.
It is very simple
to make your own.
To begin, you just need to add
a new target to your project
and select content blocker
extension from the list
of iOS application extensions.
This app extension
will be instantiated
when your content blocker
is enabled in settings.
And like all other
app extensions,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And like all other
app extensions,
it's disabled by default.
Your rules will be compiled
into byte code by Safari
so they can can be loaded
and evaluated quickly each
time Safari is launched.
Once you've created
your app extension,
you'll have an action
request handler
that looks something like this.
All this app extension
does is return the contents
of blocker list.JSON to Safari
when your app extension
is instantiated.
And blocker list.JSON
is automatically
in your extensions target,
so all you have to do
to write your own
content blocker is
to fill in this JSON file.
And content blockers are
automatically applied in Safari
or any apps that use
Safari View Controller.
If you have an app that displays
Web content you should check
out the talk from earlier
this week introducing Safari
View Controller.
However, a static block
list might not be enough
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
However, a static block
list might not be enough
for some of your apps.
You might want to
provide customization
of your content blockers, either
by letting your users select
from multiple different
block lists
or by letting your users pick
certain sites they don't want it
to apply to.
To do this, just like with other
app extensions we recommend
that you put your management
settings in your app.
When your users perform actions
that would change the contents
of your block list, all you
need to do is tell Safari
to re-instantiate
your app extension,
which will cause your content
blocker to be recompiled.
To do this, we've
added a new API
in the Safari services framework
called SF content blocker
manager reload content
blocker with identifier.
All you need to do is pass
it the bundle identifier
of your content blocker.
This will cause Safari to
rerun your app extension
and update the byte
code generated
from parsing your
content blocker.
That was just some of the things
that content blockers can do
and how easy it is to get
started making your own.
I would like to bring up Alex
Christensen to show us a demo.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I would like to bring up Alex
Christensen to show us a demo.
Alex?
[ Applause ]
>> ALEX CHRISTENSEN:
Thanks, Brian.
I'm Alex Christensen from
the Safari and WebKit team.
I'm going to show you how to
make a content blocker in iOS.
We will block content
in two ways,
we're going to hide some
elements on a Web page
and we're going to
block some loads.
Now, I don't know about you,
but I surf the Web all the time
and I feel like I can really
enhance a user's experience
by making an extension
that removes some
content from the page.
Now, let me show you one
of my favorite Web pages.
You'll see what I'm
talking about.
There we go.
Oh! Now, I just love
Web pages like this.
I got to stay up to date with
what's going on in the world
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I got to stay up to date with
what's going on in the world
of cute puppy dog pictures.
So I check one of these at
least every day and I only have
so much valuable screen space.
The comments here are kind of
annoying and they are taking
up the valuable screen
space that I want to use
for cute puppy dog pictures.
Let's go to the Web inspector
and see what we can
do about this problem.
Open up Safari on Mac.
If we go to the develop
menu, simulator,
cute puppies and cats.com.
You can see we are going
to inspect this iOS
simulator instance.
If we hold our mouse
over this we can see
that this is the div
that I want to hide.
It has a class comment.
And if we explore the structure
of this Web page we can see
that all the other
divs that I want
to hide also have
the class comment.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to hide also have
the class comment.
It's pretty easy to write
a selector div.comments
that finds all of the
elements I want to hide
on this page using the
CSS display none style.
Let's make a rule that does
that in an iOS content blocker.
Open up Xcode, create
a new project, iOS,
single view application for now.
My app. Hopefully you have
a better name than "my app".
Create it on the
desktop for now.
All right.
So from here we go to file,
new, target, and under iOS,
application extension, we have
the content blocker extension
template that Brian
just mentioned.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
My content blocker.
Let's not activate this
scheme because we will want
to run our app in
the iOS simulator.
Now, adding that new
target made this right here:
mycontentblocker.
Inside of this, it made
this blocker list.JSON.
This is where we want
to put the rules.
Now, I have a rule that applies
the selector div.comments
and applies the style
CSS display none to all
of the elements in the page
that match that selector.
And let's have this
apply everywhere for now.
So we have the dot star regular
expression, meaning everywhere.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So we have the dot star regular
expression, meaning everywhere.
Let's run this in simulator.
Here is my app.
Okay. Now if we go to settings,
Safari, content blockers,
here is my app's
content blocker.
Let's turn this on and reload
this page and see what it did.
[ Applause ]
All those comments are gone
and I can use the screen space
for the cute puppy dog pictures,
why I came to the site.
If you look really carefully,
you might notice something else
that is also not a
cute puppy dog picture.
Now, I've always been more of
a dog person than a cat person
and I don't want to
see these cat pictures.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and I don't want to
see these cat pictures.
(Laughter) I don't want to wait
for the cat pictures to load
and don't want to
use my bandwidth
to download cat pictures
that I didn't want to see
in the first place, so let's
block these loads completely.
Back in the Web inspector
and the resources tab,
you can see that the resources
on this page have some names
that I can write regular
expressions to recognize.
If it contains slash cat,
probably a cat picture.
So let's block those loads.
Here we have another rule.
Action type block, and if it
matches the regular expression
slash cat, let's block it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
slash cat, let's block it.
I think this is a
little bit too generic.
I think this will probably
block things on pages
that I'm not expecting, like
if there's slash category
in the URL anywhere on
the, this will block it
but that could cause problems.
Let's just have it
on cutepuppiesandcats.com cause
I'm pretty sure that anything
on this website that
has slash cat
in its URL is probably a cat
picture that I want to block.
All right, let's run this
and see what happens.
Let's go back to
settings and toggle this
to recompile the
content blocker.
You can also use the API to
do this from within your app.
Go back to Safari, reload
the page, there we go.
The cat pictures are gone, but
something has gone wrong here.
My dog picture is too big.
I have no background color.
It looks like the
CSS is also gone.
(Laughter) That's
definitely not what we wanted.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
(Laughter) That's
definitely not what we wanted.
Let's go back to
the Web inspector
and see what's going on.
Right here, you can see
that my CSS also starts
with /cat in its URL.
It's cats and dogs.css.
We are blocking that
unintentionally.
There are a couple ways
we could let this through.
We can have the other rule
only apply to images or --
well, be creative, but I'm
going to make it so that
if it also matches
cats and dogs,
we want to ignore this
rule that would block it.
There we go.
Has cats and dogs in it,
ignore the previous rules.
This will block the cat
pictures, which is what I want
to do, but it will let the
cats and dogs.css through.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to do, but it will let the
cats and dogs.css through.
All right, let's rerun this.
Toggle this to recompile
the content blocker
and reload the page.
There we go.
[ Applause ]
This is how I want users
of my content blocker
to view web pages like this,
straight to the puppy
dog pictures.
All right.
so today we blocked some cat
pictures, we hid some comments.
Who knows what you might
want to block tomorrow?
So give it a shot.
Try making a content
blocker on iOS.
Brian, come on back.
[ Applause ]
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Applause ]
>> BRIAN WEINSTEIN:
Thanks, Alex.
So that was an overview of how
to create a content
blocker on iOS.
And just some of the
things you can do with them.
So since we think that this
block list model is the best way
to block content on the Web
we've brought the same model
back to the Mac via
the traditional Safari
extensions API.
You have been able to block
content using Safari extensions
for a few years now,
but the current model
of blocking can actually
adversely affect performance
of your users' browsing.
With this new block list
model, since Safari knows
about the block list before
any loading takes place,
it is a lot faster.
Since we've optimized our
compiled byte code that each
of these block lists creates,
it's a lot more memory
efficient.
So if anyone has written
extensions using --
if anyone has written content
blocking extensions in the past,
they know about the
can load method
and so we are deprecating
the can load method
and if your Safari extension
specifies a block list,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and if your Safari extension
specifies a block list,
calls to can load will become
no ops in your extension.
To add a content blocker to your
Safari extension, all you have
to do is set the
content blocker file
in Safari's extension builder.
This can be the exact same JSON
file that your iOS app uses.
However, if you would
like to provide your users
with customization options
for what content to block,
once again letting them choose
between different block lists
or making a block list
not apply when a user is
on a certain page, we've
added a JavaScript API
to configure your content
blocker dynamically.
You can call
Safari.extension.set content
blocker from your
extensions global page
and pass it your
content blocker.
And the content blocker
can either be an object
or a JSON string.
This API accepts both.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So that was an overview
of content blockers
for iOS and OS X.
And while we are talking
about traditional Safari
extensions we've made some
changes to the Safari
Extensions Gallery.
And so for anyone
who is not familiar
with the Safari Extensions
Gallery, it is the best place
for your users to find
your Safari extensions.
It is directly accessible
from Safari's menu
and from Safari's
extensions preferences
and it is the only place
that your users can install your
extensions with only one click.
If you're serious about
making Safari extensions,
you are already in the gallery.
Like I said before, it is the
easiest way for your users
to discover and install
your extensions.
To make things even more
secure for our users,
coming soon all extensions
in the gallery will be both
signed and hosted by Apple.
To take advantage of
this, all you have
to do is resubmit your
extensions to the gallery.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to do is resubmit your
extensions to the gallery.
And another great
thing about this is
that once you've submitted
a version to the gallery,
if you submit an update your
users will get automatic updates
of your extension for free.
You don't have to write an
update manifest anymore.
But if you have a version
that is not in the gallery,
when you want your users to
update to your newest version
in the gallery, you
need to add a new flag
to your update manifest
saying that we,
Safari should update
your extension
to the version in the gallery.
Also coming soon, the automatic
updates will only be available
for extensions in the
Extensions Gallery.
So those were the changes to
the Safari Extensions Gallery.
I would like to move on to
the last topic of the session,
Shared Links app extensions.
Shared Links is a Safari feature
that shows up next to your list
of bookmarks and reading lists.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of bookmarks and reading lists.
It contains a stream of links
from various sources
you are interested in.
Links will show up from
your Twitter, LinkedIn,
and Weibo accounts
automatically.
Additionally, in iOS 8
and Safari for Yosemite,
we added the ability
for users to subscribe
to their favorite websites'
RSS feeds to get them to show
up directly in Shared Links.
In this screen shot you can see
links from my Twitter account
and some websites I
subscribe to, interspersed.
In iOS 9 and Safari for OS X El
Capitan, we're adding a new way
for you to get your
content directly
into Safari's Shared Links,
and they are Shared
Links app extensions.
It's a new type of app extension
that has the same
API for iOS and OS X.
To get started you create
a new app extension just
like we talked about
for content blocking.
You create a new target, and
select Shared Links extension
on the platform you're
interested in.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on the platform you're
interested in.
How an app extension works
on a high level is that,
your app extension is
called at the right time
and you return a list
of NSExtension items.
In the case of a Shared
Links app extension,
every NSExtension
item turns directly
into a Shared Links item.
We have a blank slate
of an NSExtension item
and we have the Shared Links
item we are trying to create.
I would like to take you
through the code to do this.
We start by defining some user
info on the NSExtension item,
and the first thing we
define is an identifier
for each NSExtension item.
No two NSExtension items
that your app extension returns
can have the same identifier.
Next we define the URL string
and this is just what's loaded
when the user selects your
Shared Links item in Safari.
Next, we define the published
date of the Shared Links item
and Safari uses the date of
each item to intersperse items
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and Safari uses the date of
each item to intersperse items
from various sources inside
of your user Shared Links.
Lastly, you can define a display
name which shows up at the top
of the Shared Links item.
A couple notes.
Unique identifier
must be consistent
across multiple instantiations
of your extension.
So if your extension gets
called multiple times
and returns the same
Shared Links item,
the unique identifier needs
to be the same both times
and display name is
completely optional.
If it is not set, Safari will
just use the display name
of your Shared Links
app extension.
Next, we define the title
of the Shared Links item,
which is just the attributed the
title of the NSExtension item.
Then we define the description
text of the Shared Links item,
which is just the
attributed content text
of the NSExtension item.
Both of these will be
automatically ellipsized
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Both of these will be
automatically ellipsized
for you if they are too long.
So that was all the text
of the Shared Links item.
What about the images
that we see?
The icon in the top left
corner is the first entry
in the NSExtension
items attachments array.
In this example I'm using an
image from my extensions bundle
but you could fetch an
image from the Web here.
And the icon in the top right
corner is just your apps icon.
So if you're returning
multiple Shared Links items
and with different
display names,
the icon in the top right corner
will provide your app's branding
and to let your users know that
this content is from your app.
A pro tip, if this is your first
time using NSExtension item,
all of the properties
on NSExtension item,
the attributed title, the
attributed content text
and attachment, must be set
after setting the user info.
That's all it takes to get your
content inside Shared Links.
I would like to bring Alex
back up to give another demo.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I would like to bring Alex
back up to give another demo.
Alex?
[ Applause ]
>> ALEX CHRISTENSEN: All right.
I have some content that I want
to put in with the Shared Links.
I'm going to make a
Shared Links extension.
Let me show you what
I'm talking about first.
All right.
If we open up Safari, you
can see here in the side bar
that I have a bunch of
links from my Twitter feed.
This is where I want to
put my content for users
of my Shared Links extension.
So let's make a Shared
Links extension.
Open up Xcode.
Create a new project.
Let's make it for OS X, but you
can do the same thing for iOS.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Put it on the desktop for now.
Okay. Now, from here we
go to file, new, target,
and under OS X application
extension we have the Shared
Links extension template
that Brian just showed you.
Let's go to next.
My Shared Links extension.
That's a good name.
Activate my extension scheme.
Yeah, let's activate
it, because we'll want
to run the extension
with Safari.
Now, that new target -- whoa --
made this My Shared
Links extension
and it put some template
Swift right here.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And this Swift is
pretty straightforward.
It just creates an NSExtension
item, populates its user info,
gives it an attributed
title and some context text.
Content text, excuse me.
And it calls complete request
returning items with an array
of in this case one item.
Let's see what it does
right out of the box.
Let's run it with Safari.
We are debugging
this with Xcode.
Instruments wants to
know what's going on.
There we go.
Now, right here we
have something
from My Shared Links
extension and if I click on it,
then it takes me to
Apple.com, which is great.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
then it takes me to
Apple.com, which is great.
That's what the template
said to do.
Now, this is where I want
to put my content, though.
So I'm going to modify
this Swift a little bit.
And let me go through
with you what this does.
It's pretty straightforward,
it just sends an NSURL
request to my server.
HTTPS, make sure you use HTTPS,
cutepuppiesandcats.com
slash data.JSON.
Let me show you the data
that will be received
when this request is sent.
It is just a JSON API with
some links and some content
that I might want to put
into the Shared Links.
All right, so it will make
a request, get this JSON.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
All right, so it will make
a request, get this JSON.
It will parse that
JSON and for each value
in that parsed JSON array,
it will get some
strings out of there.
And it will populate
an NSExtension item
that it just made
with some things.
I used my URL as my unique
identifier because I know
that for my data
they are all unique.
If that's not true for
your data, then find a way
to get unique values
for each of these.
I have an icon that
I need to add.
There we go.
There's my puppy icon.
I put it in the wrong place.
Let's put it in this demo.
I need to add it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Adding puppy icon.
And I need to also
add it to this target,
My Shared Links extension,
so My Shared Links extension
has access to this icon.
And let's run this.
Let's see what it does.
Let's close Safari first.
There we go.
Let's run this and
see what it does.
Instruments still wants
to know what's going on.
And my content is
not showing up.
Let's see what went wrong.
If you see right here, we
have a bunch of errors.
If you open up the
console and look
at the sys log console
you'll see a bunch
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
at the sys log console
you'll see a bunch
of sandbox exceptions.
And that's because my
extension is sandboxed;
to keep users safe,
these extensions only have
access to what they need to.
This particular extension
right now does not have access
to the network.
So we are trying to
make an NSURL request,
we definitely need
access to the network.
So if I click on
the project here,
and then go to capabilities,
right here I need
to check outgoing connections
to let this extension have
the ability to be able to send
and initiate outgoing
connections
to get this JSON data.
All right.
Now, let's run it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
There we go!
[ Applause ]
Right where we wanted it.
Now we have my content
and links to my content
so I can take users
to my website
from the Safari Shared Links.
So if you have some
content that you want to put
in the Safari Shared Links, try
making a Shared Links extension.
All right, back to you, Brian!
[ Applause ]
>> BRIAN WEINSTEIN:
Thanks, Alex,
for showing us just
how easy it is
to help your users discover
your content using Shared Links
app extensions.
So what have we talked
about today?
We've unleashed the
ability for you
to write content
blockers for iOS.
If you have a content
blocker on the Mac,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
If you have a content
blocker on the Mac,
you should definitely
adopt this new API.
It will give your
users a much faster
and more memory efficient
browsing experience.
And if you have an extension in
the Safari Extensions Gallery,
please submit it again so
your new version can be signed
and hosted by Apple.
If you don't have
an extension there,
this is a great time to start.
Lastly, if you have a set
of links that makes sense
in Shared Links, you now have
the power to put them directly
into Safari where your
users can discover them
and go back to your website.
If you have any more
questions, contact John Davis,
the Web technologies
evangelist and coming soon,
we will have a blog
post detailing all
of the capabilities of
content blocking for Safari
on the WebKit.org blog.
Feel free to contact us on
the Apple developer forums.
Related sessions,
if you have an app
that displays Web content check
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that displays Web content check
out the talk Introducing
Safari View Controller.
As you saw, we used
Web inspector
to help create content blockers.
For more information
about Web inspector,
check out Using Safari
to Deliver
and Debug a Responsive Web
Design, and I will be --
Alex and I will be in Media
Lab A directly after this.
Come find us if you
have any questions.
Thank you!
Enjoy the rest of your Friday.
[ Applause ]