1// Copyright 2013 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#include "chrome/browser/profile_resetter/profile_resetter.h"
6
7#include "base/bind.h"
8#include "chrome/browser/profile_resetter/profile_resetter_test_base.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/ui/browser.h"
11#include "chrome/test/base/in_process_browser_test.h"
12#include "content/public/test/test_utils.h"
13#include "net/cookies/cookie_store.h"
14#include "net/url_request/url_request_context.h"
15#include "net/url_request/url_request_context_getter.h"
16
17namespace {
18
19const char kCookieDefinition[] = "A=1";
20const char kCookieHostname[] = "http://host1";
21
22using content::BrowserThread;
23
24// RemoveCookieTester provides the user with the ability to set and get a
25// cookie for given profile.
26class RemoveCookieTester {
27 public:
28  explicit RemoveCookieTester(Profile* profile);
29  ~RemoveCookieTester();
30
31  std::string GetCookie(const std::string& host);
32  void AddCookie(const std::string& host, const std::string& definition);
33
34 private:
35  void GetCookieOnIOThread(net::URLRequestContextGetter* context_getter,
36                           const std::string& host);
37  void SetCookieOnIOThread(net::URLRequestContextGetter* context_getter,
38                           const std::string& host,
39                           const std::string& definition);
40  void GetCookieCallback(const std::string& cookies);
41  void SetCookieCallback(bool result);
42
43  void BlockUntilNotified();
44  void Notify();
45
46  std::string last_cookies_;
47  bool waiting_callback_;
48  Profile* profile_;
49  scoped_refptr<content::MessageLoopRunner> runner_;
50
51  DISALLOW_COPY_AND_ASSIGN(RemoveCookieTester);
52};
53
54RemoveCookieTester::RemoveCookieTester(Profile* profile)
55    : waiting_callback_(false),
56      profile_(profile) {
57}
58
59RemoveCookieTester::~RemoveCookieTester() {}
60
61// Returns true, if the given cookie exists in the cookie store.
62std::string RemoveCookieTester::GetCookie(const std::string& host) {
63  last_cookies_.clear();
64  DCHECK(!waiting_callback_);
65  waiting_callback_ = true;
66  BrowserThread::PostTask(
67      BrowserThread::IO, FROM_HERE,
68      base::Bind(&RemoveCookieTester::GetCookieOnIOThread,
69                 base::Unretained(this),
70                 base::Unretained(profile_->GetRequestContext()),
71                 host));
72  BlockUntilNotified();
73  return last_cookies_;
74}
75
76void RemoveCookieTester::AddCookie(const std::string& host,
77                                   const std::string& definition) {
78  DCHECK(!waiting_callback_);
79  waiting_callback_ = true;
80  BrowserThread::PostTask(
81      BrowserThread::IO, FROM_HERE,
82      base::Bind(&RemoveCookieTester::SetCookieOnIOThread,
83                 base::Unretained(this),
84                 base::Unretained(profile_->GetRequestContext()),
85                 host,
86                 definition));
87  BlockUntilNotified();
88}
89
90void RemoveCookieTester::GetCookieOnIOThread(
91    net::URLRequestContextGetter* context_getter,
92    const std::string& host) {
93  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
94  net::CookieStore* cookie_store = context_getter->
95      GetURLRequestContext()->cookie_store();
96  cookie_store->GetCookiesWithOptionsAsync(
97      GURL(host), net::CookieOptions(),
98      base::Bind(&RemoveCookieTester::GetCookieCallback,
99                 base::Unretained(this)));
100}
101
102void RemoveCookieTester::SetCookieOnIOThread(
103    net::URLRequestContextGetter* context_getter,
104    const std::string& host,
105    const std::string& definition) {
106  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
107  net::CookieStore* cookie_store = context_getter->
108      GetURLRequestContext()->cookie_store();
109  cookie_store->SetCookieWithOptionsAsync(
110      GURL(host), definition, net::CookieOptions(),
111      base::Bind(&RemoveCookieTester::SetCookieCallback,
112                 base::Unretained(this)));
113}
114
115void RemoveCookieTester::GetCookieCallback(const std::string& cookies) {
116  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
117    BrowserThread::PostTask(
118        BrowserThread::UI, FROM_HERE,
119        base::Bind(&RemoveCookieTester::GetCookieCallback,
120                   base::Unretained(this), cookies));
121    return;
122  }
123  last_cookies_ = cookies;
124  Notify();
125}
126
127void RemoveCookieTester::SetCookieCallback(bool result) {
128  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
129    BrowserThread::PostTask(
130        BrowserThread::UI, FROM_HERE,
131        base::Bind(&RemoveCookieTester::SetCookieCallback,
132                   base::Unretained(this), result));
133    return;
134  }
135  ASSERT_TRUE(result);
136  Notify();
137}
138
139void RemoveCookieTester::BlockUntilNotified() {
140  DCHECK(!runner_.get());
141  if (waiting_callback_) {
142    runner_ = new content::MessageLoopRunner;
143    runner_->Run();
144    runner_ = NULL;
145  }
146}
147
148void RemoveCookieTester::Notify() {
149  DCHECK(waiting_callback_);
150  waiting_callback_ = false;
151  if (runner_.get())
152    runner_->Quit();
153}
154
155class ProfileResetTest : public InProcessBrowserTest,
156                         public ProfileResetterTestBase {
157 protected:
158  virtual void SetUpOnMainThread() OVERRIDE {
159    resetter_.reset(new ProfileResetter(browser()->profile()));
160  }
161};
162
163
164IN_PROC_BROWSER_TEST_F(ProfileResetTest, ResetCookiesAndSiteData) {
165  RemoveCookieTester tester(browser()->profile());
166  tester.AddCookie(kCookieHostname, kCookieDefinition);
167  ASSERT_EQ(kCookieDefinition, tester.GetCookie(kCookieHostname));
168
169  ResetAndWait(ProfileResetter::COOKIES_AND_SITE_DATA);
170
171  EXPECT_EQ("", tester.GetCookie(kCookieHostname));
172}
173
174}  // namespace
175