Proposal: Chrome Extensions Cookie API

158 views
Skip to first unread message

Cynthia Lau

unread,
Feb 22, 2010, 5:43:52 PM2/22/10
to chromium-dev
Hello,

I would like to propose a new API for Chrome Extensions that provides access to browser cookies.  Please see the proposal here:


Comments and suggestions are more than welcome.

Thanks,
-Cindy Lau

Daniel Wagner-Hall

unread,
Feb 22, 2010, 10:29:35 PM2/22/10
to cind...@google.com, chromium-dev

I think that this is a very useful API would like to see it! My one
concern is that the CookieStore information is a bit vague, and I'm
not sure how it's directly applicable as it stands.

Adam Barth

unread,
Feb 23, 2010, 1:01:23 AM2/23/10
to cind...@google.com, chromium-dev
At a high level, this looks good. Detailed comments below.

== Permissions ==

How does this API interact with permissions in the manifest? Clearly,
an extension would need to request access to the cookie API. It would
be nice if we restricted access to only those cookies for the origins
in the extension's permission.

== Cookie Names ==

You seem to be assuming that a cookie is uniquely determined the the
pair (url, name). This is in fact not the case. There can be
multiple cookies with the same name for a given URL. Can't we just
return an array of cookie objects?

== getAll ==

Do we really want to give all the cookies in the entire cookie store
to the script at once? That seems like a lot. Maybe we should use
some kind of iterator pattern.

== set ==

We'll probably want to include a URL in the set method to mirror the
URL in the get method. We might be able to get away without this for
now, but we might really want this in the future given that the other
ways of setting cookies (e.g., the via HTTP headers and
document.cookie) provide this URL as context.

== Secure cookies ==

In the Cookie data structure, it seems like we'd want a boolean for
the Secure attribute. You might looks at
<https://developer.mozilla.org/en/nsICookieManager2> as an interesting
point of comparison to see if you missed anything else.

== Cookie paths ==

Why does the path attribute default to "/" ? On the wire, the path
defaults to the default-path value specified in
<http://tools.ietf.org/html/draft-ietf-httpstate-cookie>.

== Cookie domain ==

How do you intend to distinguish between host-only cookies and domain
cookies? One approach is to use a leading "." in the domain field of
the cookie data structure. Another approach is to use a separate
boolean flag. Either is probably fine, but your spec should be clear
about which you're using. To align with the Firefox API
<https://developer.mozilla.org/en/nsICookie>, we'd use a separate
boolean (which is probably best).

== Style issues ==

I'd call "expirationDate" either "expires" (to match the on-the-wire
syntax) or "expiry" (to match what this is called in the spec). Note
that Firefox uses both names for slight variations on this value (see
<https://developer.mozilla.org/en/nsICookie> and
<https://developer.mozilla.org/en/nsICookie2>).

== Deleting cookies ==

Is there an easy way to delete cookies with this API? That will
probably be a common use case, e.g., for cookie managers. It might be
a good idea to provide a specific delete method.

== Blocking cookies ==

Currently, there's no way to build a race-free cookie blocker with
this API. That might just be a limitation of the architecture,
however, because a race-free cookie blocker would need to get result
synchronously.

== Final thoughts ==

If you haven't already, I'd encourage you to read
<http://tools.ietf.org/html/draft-ietf-httpstate-cookie>. That will
give you a sense for some of the edge cases here. If you have
questions, I'm happy to answer them. If you have feedback on the spec
itself, you can either send them to me directly or to
http-...@ietf.org

Adam

> --
> Chromium Developers mailing list: chromi...@chromium.org
> View archives, change email options, or unsubscribe:
> http://groups.google.com/a/chromium.org/group/chromium-dev
>

Erik Kay

unread,
Feb 23, 2010, 1:16:31 PM2/23/10
to aba...@chromium.org, cind...@google.com, chromium-dev, joc...@chromium.org, Darin Fisher
+jochen, darin 
Darin and Jochen were recently talking about a way to do cookie blocking asynchronously.  Maybe this could be applied here as well.

Erik

Adam Barth

unread,
Feb 24, 2010, 12:04:17 AM2/24/10
to cind...@google.com, chromium-dev
I sent a proposal for an HTML cookie API (inspired by your API design)
to the whatwg list:

http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2010-February/025300.html

It might be a good idea to coordinate with that group on the Cookie
data structure if the whatwg is interested in speccing a replacement
for the document.cookie API.

Adam


On Mon, Feb 22, 2010 at 10:01 PM, Adam Barth <aba...@chromium.org> wrote:

Cynthia Lau

unread,
Feb 24, 2010, 6:53:19 PM2/24/10
to Adam Barth, chromium-dev, da...@chromium.org, joc...@chromium.org
Hi Adam,

Thanks for the comments and the link to the IETF document; that definitely helped me wrap my head around the potential edge cases.  More comments inline.

On Mon, Feb 22, 2010 at 10:01 PM, Adam Barth <aba...@chromium.org> wrote:
At a high level, this looks good.  Detailed comments below.

== Permissions ==

How does this API interact with permissions in the manifest?  Clearly,
an extension would need to request access to the cookie API.  It would
be nice if we restricted access to only those cookies for the origins
in the extension's permission.

I agree that a "cookies" permissions item could be nice. Restricting cookie access to specific origins would also probably add safety, but would remove the possibility of a Chrome Extension that could enumerate all the existing cookies for the user to provide some sort of cookie management functionality. I personally don't need this total cookie visibility for my own extension work, but it seemed like a nice-to-have. Does it compromise security too much in your opinion?
 
== Cookie Names ==

You seem to be assuming that a cookie is uniquely determined the the
pair (url, name).  This is in fact not the case.  There can be
multiple cookies with the same name for a given URL. Can't we just
return an array of cookie objects?

Okay, I wasn't aware of that. I can return an array of cookies, but then this API essentially becomes the same as getAll(), aside from domain and name being optional in getAll(). Perhaps I can just consolidate the two, allowing get() to optionally not provide a name (thus returning all cookies for the given domain).
 
== getAll ==

Do we really want to give all the cookies in the entire cookie store
to the script at once?  That seems like a lot.  Maybe we should use
some kind of iterator pattern.
I guess this discussion depends on whether we decide to restrict cookie access to a specific list of allowed hosts in the manifest permissions.
 
Assuming we don't, then as one possible solution, I could add an API that returns a list of all the existing cookie domains, and let the API user call get() on each of these domains.

If that's still too extensive, I suppose we could introduce some sort of iterator pattern; it would need to define some definitive ordering of cookies (perhaps a single iterator location providing access to a single domain string that exists in the cookie store?), and would need to be able to handle changes to the cookie store happening during iteration.

I don't see any precedents for iterators in the existing Chrome Ext APIs; would this work best as a user-provided callback that is invoked automatically on each iteration (perhaps providing a return value indicating whether to continue or end the iteration)? This seems to match the current API design reasonably well. Alternatively some sort of handle (or even a domain string itself) could represent a position in the iteration.  I am open to suggestions here.


== set ==

We'll probably want to include a URL in the set method to mirror the
URL in the get method.  We might be able to get away without this for
now, but we might really want this in the future given that the other
ways of setting cookies (e.g., the via HTTP headers and
document.cookie) provide this URL as context.

Okay, that sounds reasonable. I've added it to the proposal.
 
== Secure cookies ==

In the Cookie data structure, it seems like we'd want a boolean for
the Secure attribute.  You might looks at
<https://developer.mozilla.org/en/nsICookieManager2> as an interesting
point of comparison to see if you missed anything else.

Done.  The link you provided has a separate boolean called 'aIsSession' if the cookie is for the current session only. I had this flag implicitly indicated by the existence or absence of the expiry property.  Is it worth having an explicit bool for this?

Also, the nslCookie2 class has creationTime and lastAccessed fields. I wonder whether this is useful as part of the API or if it's overkill at this time.
 
== Cookie paths ==

Why does the path attribute default to "/" ?  On the wire, the path
defaults to the default-path value specified in
<http://tools.ietf.org/html/draft-ietf-httpstate-cookie>.

Wasn't aware of that; I've changed the proposal to match this behavior.
 
== Cookie domain ==

How do you intend to distinguish between host-only cookies and domain
cookies?  One approach is to use a leading "." in the domain field of
the cookie data structure.  Another approach is to use a separate
boolean flag.  Either is probably fine, but your spec should be clear
about which you're using.  To align with the Firefox API
<https://developer.mozilla.org/en/nsICookie>, we'd use a separate
boolean (which is probably best).

Done.
 

== Style issues ==

I'd call "expirationDate" either "expires" (to match the on-the-wire
syntax) or "expiry" (to match what this is called in the spec).  Note
that Firefox uses both names for slight variations on this value (see
<https://developer.mozilla.org/en/nsICookie> and
<https://developer.mozilla.org/en/nsICookie2>).

Going with expiry, which will have both meanings depending on whether it appears in a get or set.
 
== Deleting cookies ==

Is there an easy way to delete cookies with this API?  That will
probably be a common use case, e.g., for cookie managers.  It might be
a good idea to provide a specific delete method.

Yeah, that sounds fine. I've added it to the proposal.
 
== Blocking cookies ==

Currently, there's no way to build a race-free cookie blocker with
this API.  That might just be a limitation of the architecture,
however, because a race-free cookie blocker would need to get result
synchronously.
 
I'll wait for Darin and Jochen to weigh in on this idea.

Thanks!
-Cindy

Adam Barth

unread,
Feb 24, 2010, 9:26:00 PM2/24/10
to Cynthia Lau, chromium-dev, da...@chromium.org, joc...@chromium.org, Peter Kasting
Comments inline.

On Wed, Feb 24, 2010 at 3:53 PM, Cynthia Lau <cind...@google.com> wrote:
> Hi Adam,
> Thanks for the comments and the link to the IETF document; that definitely
> helped me wrap my head around the potential edge cases.  More comments
> inline.

Glad that was helpful.

> On Mon, Feb 22, 2010 at 10:01 PM, Adam Barth <aba...@chromium.org> wrote:
>>
>> At a high level, this looks good.  Detailed comments below.
>>
>> == Permissions ==
>>
>> How does this API interact with permissions in the manifest?  Clearly,
>> an extension would need to request access to the cookie API.  It would
>> be nice if we restricted access to only those cookies for the origins
>> in the extension's permission.
>
> I agree that a "cookies" permissions item could be nice. Restricting cookie
> access to specific origins would also probably add safety, but would remove
> the possibility of a Chrome Extension that could enumerate all the existing
> cookies for the user to provide some sort of cookie management
> functionality. I personally don't need this total cookie visibility for my
> own extension work, but it seemed like a nice-to-have. Does it compromise
> security too much in your opinion?

Keep in mind that an extension can ask for http://* and https://*, so
an extension author can get access to all the cookies if he/she is
writing a cookie manager. I think it's important for security to
restrict cookie access according to the extensions permissions because
cookies are often the most confidential information web sites have.

>> == Cookie Names ==
>>
>> You seem to be assuming that a cookie is uniquely determined the the
>> pair (url, name).  This is in fact not the case.  There can be
>> multiple cookies with the same name for a given URL. Can't we just
>> return an array of cookie objects?
>
> Okay, I wasn't aware of that. I can return an array of cookies, but then
> this API essentially becomes the same as getAll(), aside from domain and
> name being optional in getAll(). Perhaps I can just consolidate the two,
> allowing get() to optionally not provide a name (thus returning all cookies
> for the given domain).

Based on some feedback on the whatwg list from some YUI developers, it
looks like developers commonly want to retrieve a single cookie by
name. Maybe we should just return the first cookie that matches the
supplied name. That will do what the developer wants in the common
case. (Note that multiple cookies with the same name are rare.)

>> == getAll ==
>>
>> Do we really want to give all the cookies in the entire cookie store
>> to the script at once?  That seems like a lot.  Maybe we should use
>> some kind of iterator pattern.
>
> I guess this discussion depends on whether we decide to restrict cookie
> access to a specific list of allowed hosts in the manifest permissions.
>
> Assuming we don't, then as one possible solution, I could add an API that
> returns a list of all the existing cookie domains, and let the API user call
> get() on each of these domains.
> If that's still too extensive, I suppose we could introduce some sort of
> iterator pattern; it would need to define some definitive ordering of
> cookies (perhaps a single iterator location providing access to a single
> domain string that exists in the cookie store?), and would need to be able
> to handle changes to the cookie store happening during iteration.
> I don't see any precedents for iterators in the existing Chrome Ext APIs;
> would this work best as a user-provided callback that is invoked
> automatically on each iteration (perhaps providing a return value indicating
> whether to continue or end the iteration)? This seems to match the current
> API design reasonably well. Alternatively some sort of handle (or even a
> domain string itself) could represent a position in the iteration.  I am
> open to suggestions here.

We should get some feedback from Peter on this point. Peter, do you
have a sense for how large the cookie store is? Is it reasonable to
return the entire cookie store at once via an extension API?

Another thought on the getAll API is that we could take a Cookie
object as the cookeInfo parameter. The API could then return all the
cookies that match whatever properties are defined on that object.
For example, that would let the developer filter by domain.

>> == Secure cookies ==
>>
>> In the Cookie data structure, it seems like we'd want a boolean for
>> the Secure attribute.  You might looks at
>> <https://developer.mozilla.org/en/nsICookieManager2> as an interesting
>> point of comparison to see if you missed anything else.
>>
> Done.  The link you provided has a separate boolean called 'aIsSession' if
> the cookie is for the current session only. I had this flag implicitly
> indicated by the existence or absence of the expiry property.  Is it worth
> having an explicit bool for this?

I don't think we need an extra bool for this property.

> Also, the nslCookie2 class has creationTime and lastAccessed fields. I
> wonder whether this is useful as part of the API or if it's overkill at this
> time.

They're probably not necessary at this time. We have them internally.
I guess they might be useful, but it seems like extra complexity that
we might not need.

Adam

Jochen Eisinger

unread,
Feb 25, 2010, 3:14:21 AM2/25/10
to Cynthia Lau, Adam Barth, chromium-dev, da...@chromium.org
Hi,

(reposting from the correct email addr)

On Thu, Feb 25, 2010 at 12:53 AM, Cynthia Lau <cind...@google.com> wrote:
>> == Blocking cookies ==
>>
>> Currently, there's no way to build a race-free cookie blocker with
>> this API.  That might just be a limitation of the architecture,
>> however, because a race-free cookie blocker would need to get result
>> synchronously.
>>
>
> I'll wait for Darin and Jochen to weigh in on this idea.


I'm thinking about ways to ask the user about what to do with a cookie
without blocking the browser. That requires some way to defer blocking
decisions. However, this is still just a rough idea...

As far as I understood this proposal, it's point is more about
observing cookies, and handling them in a similar way as in-page
javascript can do for its own cookies. I'm not sure whether it's a
good idea to also include network level cookie blocking to this api.

best
-jochen

Cynthia Lau

unread,
Feb 25, 2010, 1:09:37 PM2/25/10
to Daniel Wagner-Hall, chromium-dev
Hi Daniel,

I think that this is a very useful API would like to see it! My one
concern is that the CookieStore information is a bit vague, and I'm
not sure how it's directly applicable as it stands.

Matt Perry is working on support for incognito extensions, with incognito windows accessible by tab ID. Such extensions would need to be able to associate cookie stores with windows/tabs.

-Cindy

Erik Kay

unread,
Feb 25, 2010, 1:16:22 PM2/25/10
to joc...@chromium.org, Cynthia Lau, Adam Barth, chromium-dev, da...@chromium.org
While that was the initial use case, once you have the cookie API, cookie blocking is an obvious feature request from extension devs.  If you have a good mechanism where cookie blocking decisions can be deferred, I'd say it's a candidate to include in an extensions cookie API.  On the flip side, I understand you've only just started to take a look at the issue, so it's probably premature to think about it in the API.  I just figured that you might have some useful comments to add.

Erik
 

best
-jochen

Cynthia Lau

unread,
Feb 25, 2010, 3:07:48 PM2/25/10
to Adam Barth, chromium-dev, da...@chromium.org, joc...@chromium.org, Peter Kasting
Hi Adam,
 
Keep in mind that an extension can ask for http://* and https://*, so
an extension author can get access to all the cookies if he/she is
writing a cookie manager.  I think it's important for security to
restrict cookie access according to the extensions permissions because
cookies are often the most confidential information web sites have.

Okay, that does make sense. I've added a Manifest section to the proposal API spec that mentions a "cookies" permission as well as match patterns for cross-origin permissions.

 
>> == Cookie Names ==
>>
>> You seem to be assuming that a cookie is uniquely determined the the
>> pair (url, name).  This is in fact not the case.  There can be
>> multiple cookies with the same name for a given URL. Can't we just
>> return an array of cookie objects?
>
> Okay, I wasn't aware of that. I can return an array of cookies, but then
> this API essentially becomes the same as getAll(), aside from domain and
> name being optional in getAll(). Perhaps I can just consolidate the two,
> allowing get() to optionally not provide a name (thus returning all cookies
> for the given domain).

Based on some feedback on the whatwg list from some YUI developers, it
looks like developers commonly want to retrieve a single cookie by
name.  Maybe we should just return the first cookie that matches the
supplied name.  That will do what the developer wants in the common
case.  (Note that multiple cookies with the same name are rare.)

Okay, sounds good. I've added a note to the get() description that more than one cookie may match the given URL and name; in that case the first one returned can match the precedence order you described in http://tools.ietf.org/html/draft-ietf-httpstate-cookie-04#section-5.4--longest path first, or earliest creation time. What about most-specific domain?  Seems like a host-only cookie should be returned before one with a more general matching domain.
I don't think a Cookie object alone would be sufficient for the cookieInfo parameter; for instance, if I want to simply get all the cookies that would be returned for a particular request URL, then the current cookieInfo.url property I define is more appropriate for that.

Maybe I can modify cookieInfo to have an optional cookieInfo.matchFilter of type Cookie, which will filter cookies as you describe above. But then, I could still see a little bit of confusion; right now, for instance, I define cookieInfo.includeHttpOnly, which has the nice property IMHO of forcing the user to explicitly state when they intend to access HttpOnly cookies.  

Using cookieInfo.matchFilter.httpOnly would have a different meaning, and not setting that property in a call to getAll() would seem to imply that all cookies, whether HttpOnly or not, should be returned by default. Would we want to implement both of these options in getAll(), or get rid of one of them?

-Cindy

Adam Barth

unread,
Feb 25, 2010, 3:14:32 PM2/25/10
to Cynthia Lau, chromium-dev, da...@chromium.org, joc...@chromium.org, Peter Kasting
On Thu, Feb 25, 2010 at 12:07 PM, Cynthia Lau <cind...@google.com> wrote:
>> >> == Cookie Names ==
>> >>
>> >> You seem to be assuming that a cookie is uniquely determined the the
>> >> pair (url, name).  This is in fact not the case.  There can be
>> >> multiple cookies with the same name for a given URL. Can't we just
>> >> return an array of cookie objects?
>> >
>> > Okay, I wasn't aware of that. I can return an array of cookies, but then
>> > this API essentially becomes the same as getAll(), aside from domain and
>> > name being optional in getAll(). Perhaps I can just consolidate the two,
>> > allowing get() to optionally not provide a name (thus returning all
>> > cookies
>> > for the given domain).
>>
>> Based on some feedback on the whatwg list from some YUI developers, it
>> looks like developers commonly want to retrieve a single cookie by
>> name.  Maybe we should just return the first cookie that matches the
>> supplied name.  That will do what the developer wants in the common
>> case.  (Note that multiple cookies with the same name are rare.)
>>
> Okay, sounds good. I've added a note to the get() description that more than
> one cookie may match the given URL and name; in that case the first one
> returned can match the precedence order you described
> in http://tools.ietf.org/html/draft-ietf-httpstate-cookie-04#section-5.4--longest
> path first, or earliest creation time. What about most-specific domain?
>  Seems like a host-only cookie should be returned before one with a more
> general matching domain.

That section of the spec is still under debate. What I would say is
that the API should return the first cookie with that name that would
appear in the Cookie header. That way it's the CookieMonster's
problem to figure out the proper ordering.

I like the idea of having to explicitly ask for HttpOnly cookies. You
seem to be considering the right factors here. I think you should use
your best judgement as the designer of the API.

Adam

Cynthia Lau

unread,
Mar 1, 2010, 5:47:24 PM3/1/10
to Adam Barth, chromium-dev, da...@chromium.org, joc...@chromium.org, Peter Kasting
Okay, I've once again modified the cookie API proposal. Based on Jochen's comments, it sounds like adding cookie blocking support might be premature at this time.

Any more feedback on the proposal?

Thanks,
-Cindy

Cynthia Lau

unread,
Mar 1, 2010, 5:48:14 PM3/1/10
to Adam Barth, chromium-dev, da...@chromium.org, joc...@chromium.org, Peter Kasting
Oh, and I added the proposal to the Chromium Dev wiki, now that I have access; the new up-to-date location is here:


Thanks!
-Cindy

Adam Barth

unread,
Mar 1, 2010, 6:40:25 PM3/1/10
to Cynthia Lau, chromium-dev, da...@chromium.org, joc...@chromium.org, Peter Kasting
There are some formatting issues with the wiki, but otherwise, this
looks good to me. Maybe it's time for a prototype implementation to
get some implementation experience?

Adam

Peter Kasting

unread,
Mar 1, 2010, 8:16:04 PM3/1/10
to Adam Barth, Cynthia Lau, chromium-dev, da...@chromium.org, joc...@chromium.org
I'm sorry, I entirely missed this question.

The cookie store right now clamps at 3000 cookies.  Users are very likely to be at this limit.  In the future, we may shift to a model where there is no limit for recently-accessed cookies, which is likely to push the number over 10,000 cookies (maybe to ~20,000 cookies).  Whether you want to return that many objects at once I have no idea; I don't have a feeling for the perf impacts here.

Note that local storage, database etc. are not considered in the above limits.

Jeremy Orlow

unread,
Mar 1, 2010, 8:22:31 PM3/1/10
to pkas...@google.com, Adam Barth, Cynthia Lau, chromium-dev, da...@chromium.org, joc...@chromium.org, Dumitru Daniliuc
We don't have any limits in localStorage or database.  LocalStorage would only hit scaling problems related to this if the number of files in the directory becomes a problem for the OS.  Database has a central db for tracking quota and such.  I'm not sure if we've ever measured at what point it'd start falling over.  Things to perhaps think about in the future, I suppose.

--

Jochen Eisinger

unread,
Mar 12, 2010, 8:58:26 AM3/12/10
to Adam Barth, Cynthia Lau, chromium-dev, da...@chromium.org, Peter Kasting
since I want to play around a bit with this API, I started implementing it.

-j

Cynthia Lau

unread,
Mar 12, 2010, 10:58:38 AM3/12/10
to Jochen Eisinger, Adam Barth, chromium-dev, da...@chromium.org, Peter Kasting
Hm, I've already started implementing it too; I've got the JSON written out and api tests in place, and have started implementing cookies.get.  Should I submit what I have so we don't collide?  What are you starting with?

-Cindy

Jochen Eisinger

unread,
Mar 12, 2010, 11:23:24 AM3/12/10
to Cynthia Lau, Adam Barth, chromium-dev, da...@chromium.org, Peter Kasting
oh, I really just started looking at it. If you could share your
current state with me (and maybe a pointer which part i should
implement), I'd be happy to help!

-j

Reply all
Reply to author
Forward
0 new messages