1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_COOKIE_STORE_H_
6#define CHROME_BROWSER_PRERENDER_PRERENDER_COOKIE_STORE_H_
7
8#include <set>
9#include <string>
10#include <vector>
11
12#include "base/callback.h"
13#include "base/compiler_specific.h"
14#include "base/macros.h"
15#include "base/memory/ref_counted.h"
16#include "net/cookies/cookie_monster.h"
17#include "net/cookies/cookie_store.h"
18#include "url/gurl.h"
19
20namespace prerender {
21
22// A cookie store which keeps track of provisional changes to the cookie monster
23// of an underlying request context (called the default cookie monster).
24// Initially, it will proxy read requests to the default cookie monster, and
25// copy on write keys that are being modified into a private cookie monster.
26// Reads for these will then happen from the private cookie monster.
27// Should keys be modified in the default cookie store, the corresponding
28// prerender should be aborted.
29// This class also keeps a log of all cookie transactions. Once ApplyChanges
30// is called, the changes will be applied to the default cookie monster,
31// and any future requests to this object will simply be forwarded to the
32// default cookie monster. After ApplyChanges is called, the prerender tracker,
33// which "owns" the PrerenderCookieStore reference, will remove its entry for
34// the PrerenderCookieStore. Therefore, after ApplyChanges is called, the
35// object will only stick around (and exhibit forwarding mode) as long as
36// eg pending requests hold on to its reference.
37class PrerenderCookieStore : public net::CookieStore {
38 public:
39  // Creates a PrerenderCookieStore using the default cookie monster provided
40  // by the URLRequestContext. The underlying cookie store must be loaded,
41  // ie it's call to loaded() must return true.
42  // Otherwise, copying cookie data between the prerender cookie store
43  // (used to only commit cookie changes once a prerender is shown) would
44  // not work synchronously, which would complicate the code.
45  // |cookie_conflict_cb| will be called when a cookie conflict is detected.
46  // The callback will be run on the UI thread.
47  PrerenderCookieStore(scoped_refptr<net::CookieMonster> default_cookie_store_,
48                       const base::Closure& cookie_conflict_cb);
49
50  // CookieStore implementation
51  virtual void SetCookieWithOptionsAsync(
52      const GURL& url,
53      const std::string& cookie_line,
54      const net::CookieOptions& options,
55      const SetCookiesCallback& callback) OVERRIDE;
56
57  virtual void GetCookiesWithOptionsAsync(
58      const GURL& url,
59      const net::CookieOptions& options,
60      const GetCookiesCallback& callback) OVERRIDE;
61
62  virtual void GetAllCookiesForURLAsync(
63      const GURL& url,
64      const GetCookieListCallback& callback) OVERRIDE;
65
66  virtual void DeleteCookieAsync(const GURL& url,
67                                 const std::string& cookie_name,
68                                 const base::Closure& callback) OVERRIDE;
69
70  // All the following methods should not be used in the scenarios where
71  // a PrerenderCookieStore is used. This will be checked via NOTREACHED().
72  // Should PrerenderCookieStore used in contexts requiring these, they will
73  // need to be implemented first. They are only intended to be called on the
74  // IO thread.
75
76  virtual void DeleteAllCreatedBetweenAsync(
77      const base::Time& delete_begin,
78      const base::Time& delete_end,
79      const DeleteCallback& callback) OVERRIDE;
80
81  virtual void DeleteAllCreatedBetweenForHostAsync(
82      const base::Time delete_begin,
83      const base::Time delete_end,
84      const GURL& url,
85      const DeleteCallback& callback) OVERRIDE;
86
87  virtual void DeleteSessionCookiesAsync(const DeleteCallback&) OVERRIDE;
88
89  virtual net::CookieMonster* GetCookieMonster() OVERRIDE;
90
91  // Commits the changes made to the underlying cookie store, and switches
92  // into forwarding mode. To be called on the IO thread.
93  // |cookie_change_urls| will be populated with all URLs for which cookies
94  // were updated.
95  void ApplyChanges(std::vector<GURL>* cookie_change_urls);
96
97  // Called when a cookie for a URL is changed in the underlying default cookie
98  // store. To be called on the IO thread. If the key corresponding to the URL
99  // was copied or read, the prerender will be cancelled.
100  void OnCookieChangedForURL(net::CookieMonster* cookie_monster,
101                             const GURL& url);
102
103  net::CookieMonster* default_cookie_monster() {
104    return default_cookie_monster_.get();
105  }
106
107 private:
108  enum CookieOperationType {
109    COOKIE_OP_SET_COOKIE_WITH_OPTIONS_ASYNC,
110    COOKIE_OP_GET_COOKIES_WITH_OPTIONS_ASYNC,
111    COOKIE_OP_GET_ALL_COOKIES_FOR_URL_ASYNC,
112    COOKIE_OP_DELETE_COOKIE_ASYNC,
113    COOKIE_OP_MAX
114  };
115
116  struct CookieOperation {
117    CookieOperationType op;
118    GURL url;
119    net::CookieOptions options;
120    std::string cookie_line;
121    std::string cookie_name;
122    CookieOperation();
123    ~CookieOperation();
124  };
125
126  virtual ~PrerenderCookieStore();
127
128  // Gets the appropriate cookie store for the operation provided, and pushes
129  // it back on the log of cookie operations performed.
130  net::CookieStore* GetCookieStoreForCookieOpAndLog(const CookieOperation& op);
131
132  // Indicates whether the changes have already been applied (ie the prerender
133  // has been shown), and we are merely in forwarding mode;
134  bool in_forwarding_mode_;
135
136  // The default cookie monster.
137  scoped_refptr<net::CookieMonster> default_cookie_monster_;
138
139  // A cookie monster storing changes made by the prerender.
140  // Entire keys are copied from default_cookie_monster_ on change, and then
141  // modified.
142  scoped_refptr<net::CookieMonster> changes_cookie_monster_;
143
144  // Log of cookie operations performed
145  std::vector<CookieOperation> cookie_ops_;
146
147  // The keys which have been copied on write to |changes_cookie_monster_|.
148  std::set<std::string> copied_keys_;
149
150  // Keys which have been read (but not necessarily been modified).
151  std::set<std::string> read_keys_;
152
153  // Callback when a cookie conflict was detected
154  base::Closure cookie_conflict_cb_;
155
156  // Indicates whether a cookie conflict has been detected yet.
157  bool cookie_conflict_;
158
159  DISALLOW_COPY_AND_ASSIGN(PrerenderCookieStore);
160};
161
162}  // namespace prerender
163
164#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_COOKIE_STORE_H_
165