blob: 1a34a18919a05353cbe38dc0aca11da7ba966f10 [file] [log] [blame]
[email protected]aa84a7e2012-03-15 21:29:061// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]898bbd32010-05-18 18:52:292// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]b7e899142010-06-02 17:03:325// Implements the Chrome Extensions Cookies API.
6
[email protected]92ba7b012012-05-16 03:36:177#include "chrome/browser/extensions/api/cookies/cookies_api.h"
[email protected]898bbd32010-05-18 18:52:298
[email protected]960927c02012-07-23 21:38:089#include <vector>
10
[email protected]b9e48094d2011-07-20 14:27:1311#include "base/bind.h"
[email protected]2c5e1e12010-06-10 13:14:4412#include "base/json/json_writer.h"
[email protected]1794e6a2013-01-03 02:22:0213#include "base/lazy_instance.h"
[email protected]960927c02012-07-23 21:38:0814#include "base/memory/linked_ptr.h"
15#include "base/memory/scoped_ptr.h"
[email protected]ccc91c62012-09-11 01:02:4316#include "base/time.h"
[email protected]3bb84992010-08-26 17:23:4617#include "base/values.h"
[email protected]92ba7b012012-05-16 03:36:1718#include "chrome/browser/extensions/api/cookies/cookies_api_constants.h"
19#include "chrome/browser/extensions/api/cookies/cookies_helpers.h"
[email protected]5a38dfd2012-07-23 23:22:1020#include "chrome/browser/extensions/event_router.h"
[email protected]9e5be1f92012-10-29 19:01:4521#include "chrome/browser/extensions/extension_system.h"
[email protected]8ecad5e2010-12-02 21:18:3322#include "chrome/browser/profiles/profile.h"
[email protected]d8748142012-05-16 21:13:4323#include "chrome/browser/ui/browser.h"
[email protected]71b73f02011-04-06 15:57:2924#include "chrome/browser/ui/browser_list.h"
[email protected]432115822011-07-10 15:52:2725#include "chrome/common/chrome_notification_types.h"
[email protected]960927c02012-07-23 21:38:0826#include "chrome/common/extensions/api/cookies.h"
[email protected]d83a5602010-09-16 00:22:4827#include "chrome/common/extensions/extension.h"
[email protected]c38831a12011-10-28 12:44:4928#include "content/public/browser/browser_thread.h"
[email protected]ad50def52011-10-19 23:17:0729#include "content/public/browser/notification_service.h"
[email protected]e9f541a2012-11-19 21:52:3130#include "extensions/common/error_utils.h"
[email protected]5b9bc352012-07-18 13:13:3431#include "net/cookies/canonical_cookie.h"
[email protected]aa84a7e2012-03-15 21:29:0632#include "net/cookies/cookie_monster.h"
[email protected]277ec262011-03-30 21:09:4033#include "net/url_request/url_request_context.h"
[email protected]abe2c032011-03-31 18:49:3434#include "net/url_request/url_request_context_getter.h"
[email protected]898bbd32010-05-18 18:52:2935
[email protected]631bb742011-11-02 11:29:3936using content::BrowserThread;
[email protected]960927c02012-07-23 21:38:0837using extensions::api::cookies::Cookie;
38using extensions::api::cookies::CookieStore;
39
40namespace Get = extensions::api::cookies::Get;
41namespace GetAll = extensions::api::cookies::GetAll;
42namespace GetAllCookieStores = extensions::api::cookies::GetAllCookieStores;
43namespace Remove = extensions::api::cookies::Remove;
44namespace Set = extensions::api::cookies::Set;
[email protected]631bb742011-11-02 11:29:3945
[email protected]92ba7b012012-05-16 03:36:1746namespace extensions {
47namespace keys = cookies_api_constants;
[email protected]898bbd32010-05-18 18:52:2948
[email protected]c54115c2012-12-06 17:56:3049CookiesEventRouter::CookiesEventRouter(Profile* profile)
[email protected]960927c02012-07-23 21:38:0850 : profile_(profile) {
[email protected]f825df22011-06-28 17:36:1051 CHECK(registrar_.IsEmpty());
52 registrar_.Add(this,
[email protected]432115822011-07-10 15:52:2753 chrome::NOTIFICATION_COOKIE_CHANGED,
[email protected]ad50def52011-10-19 23:17:0754 content::NotificationService::AllBrowserContextsAndSources());
[email protected]2c5e1e12010-06-10 13:14:4455}
56
[email protected]c54115c2012-12-06 17:56:3057CookiesEventRouter::~CookiesEventRouter() {
[email protected]ab9356c2012-11-05 23:13:2658}
59
[email protected]c54115c2012-12-06 17:56:3060void CookiesEventRouter::Observe(
[email protected]6c2381d2011-10-19 02:52:5361 int type,
62 const content::NotificationSource& source,
63 const content::NotificationDetails& details) {
64 Profile* profile = content::Source<Profile>(source).ptr();
[email protected]ccc91c62012-09-11 01:02:4365 if (!profile_->IsSameProfile(profile))
[email protected]f825df22011-06-28 17:36:1066 return;
[email protected]ccc91c62012-09-11 01:02:4367
[email protected]432115822011-07-10 15:52:2768 switch (type) {
69 case chrome::NOTIFICATION_COOKIE_CHANGED:
[email protected]2c5e1e12010-06-10 13:14:4470 CookieChanged(
[email protected]f825df22011-06-28 17:36:1071 profile,
[email protected]6c2381d2011-10-19 02:52:5372 content::Details<ChromeCookieDetails>(details).ptr());
[email protected]2c5e1e12010-06-10 13:14:4473 break;
74
75 default:
76 NOTREACHED();
77 }
78}
79
[email protected]c54115c2012-12-06 17:56:3080void CookiesEventRouter::CookieChanged(
[email protected]2c5e1e12010-06-10 13:14:4481 Profile* profile,
82 ChromeCookieDetails* details) {
[email protected]c9bd90f2012-08-07 23:58:1583 scoped_ptr<ListValue> args(new ListValue());
[email protected]2c5e1e12010-06-10 13:14:4484 DictionaryValue* dict = new DictionaryValue();
85 dict->SetBoolean(keys::kRemovedKey, details->removed);
[email protected]960927c02012-07-23 21:38:0886
87 scoped_ptr<Cookie> cookie(
88 cookies_helpers::CreateCookie(*details->cookie,
[email protected]ccc91c62012-09-11 01:02:4389 cookies_helpers::GetStoreIdFromProfile(profile_)));
[email protected]960927c02012-07-23 21:38:0890 dict->Set(keys::kCookieKey, cookie->ToValue().release());
[email protected]8bb846f2011-03-23 12:08:1891
[email protected]ccc91c62012-09-11 01:02:4392 // Map the internal cause to an external string.
[email protected]8bb846f2011-03-23 12:08:1893 std::string cause;
94 switch (details->cause) {
95 case net::CookieMonster::Delegate::CHANGE_COOKIE_EXPLICIT:
96 cause = keys::kExplicitChangeCause;
97 break;
98
99 case net::CookieMonster::Delegate::CHANGE_COOKIE_OVERWRITE:
100 cause = keys::kOverwriteChangeCause;
101 break;
102
103 case net::CookieMonster::Delegate::CHANGE_COOKIE_EXPIRED:
104 cause = keys::kExpiredChangeCause;
105 break;
106
107 case net::CookieMonster::Delegate::CHANGE_COOKIE_EVICTED:
108 cause = keys::kEvictedChangeCause;
109 break;
110
[email protected]e7c590e52011-03-30 08:33:55111 case net::CookieMonster::Delegate::CHANGE_COOKIE_EXPIRED_OVERWRITE:
112 cause = keys::kExpiredOverwriteChangeCause;
113 break;
114
[email protected]8bb846f2011-03-23 12:08:18115 default:
116 NOTREACHED();
117 }
118 dict->SetString(keys::kCauseKey, cause);
119
[email protected]c9bd90f2012-08-07 23:58:15120 args->Append(dict);
[email protected]2c5e1e12010-06-10 13:14:44121
[email protected]2c5e1e12010-06-10 13:14:44122 GURL cookie_domain =
[email protected]92ba7b012012-05-16 03:36:17123 cookies_helpers::GetURLFromCanonicalCookie(*details->cookie);
[email protected]c9bd90f2012-08-07 23:58:15124 DispatchEvent(profile, keys::kOnChanged, args.Pass(), cookie_domain);
[email protected]2c5e1e12010-06-10 13:14:44125}
126
[email protected]c54115c2012-12-06 17:56:30127void CookiesEventRouter::DispatchEvent(
[email protected]ccc91c62012-09-11 01:02:43128 Profile* profile,
129 const std::string& event_name,
130 scoped_ptr<ListValue> event_args,
[email protected]c9bd90f2012-08-07 23:58:15131 GURL& cookie_domain) {
[email protected]9e5be1f92012-10-29 19:01:45132 EventRouter* router = profile ?
133 extensions::ExtensionSystem::Get(profile)->event_router() : NULL;
[email protected]ccc91c62012-09-11 01:02:43134 if (!router)
135 return;
[email protected]01f7a8042012-12-07 07:48:02136 scoped_ptr<Event> event(new Event(event_name, event_args.Pass()));
137 event->restrict_to_profile = profile;
138 event->event_url = cookie_domain;
139 router->BroadcastEvent(event.Pass());
[email protected]2c5e1e12010-06-10 13:14:44140}
141
[email protected]960927c02012-07-23 21:38:08142bool CookiesFunction::ParseUrl(const std::string& url_string, GURL* url,
[email protected]b7e899142010-06-02 17:03:32143 bool check_host_permissions) {
[email protected]898bbd32010-05-18 18:52:29144 *url = GURL(url_string);
145 if (!url->is_valid()) {
[email protected]e9f541a2012-11-19 21:52:31146 error_ = ErrorUtils::FormatErrorMessage(
[email protected]898bbd32010-05-18 18:52:29147 keys::kInvalidUrlError, url_string);
148 return false;
149 }
[email protected]b7e899142010-06-02 17:03:32150 // Check against host permissions if needed.
[email protected]ccc91c62012-09-11 01:02:43151 if (check_host_permissions && !GetExtension()->HasHostPermission(*url)) {
[email protected]e9f541a2012-11-19 21:52:31152 error_ = ErrorUtils::FormatErrorMessage(
[email protected]b7e899142010-06-02 17:03:32153 keys::kNoHostPermissionsError, url->spec());
154 return false;
155 }
[email protected]898bbd32010-05-18 18:52:29156 return true;
157}
158
[email protected]960927c02012-07-23 21:38:08159bool CookiesFunction::ParseStoreContext(
160 std::string* store_id,
161 net::URLRequestContextGetter** context) {
162 DCHECK((context || store_id->empty()));
[email protected]898bbd32010-05-18 18:52:29163 Profile* store_profile = NULL;
[email protected]960927c02012-07-23 21:38:08164 if (!store_id->empty()) {
[email protected]92ba7b012012-05-16 03:36:17165 store_profile = cookies_helpers::ChooseProfileFromStoreId(
[email protected]960927c02012-07-23 21:38:08166 *store_id, profile(), include_incognito());
[email protected]898bbd32010-05-18 18:52:29167 if (!store_profile) {
[email protected]e9f541a2012-11-19 21:52:31168 error_ = ErrorUtils::FormatErrorMessage(
[email protected]960927c02012-07-23 21:38:08169 keys::kInvalidStoreIdError, *store_id);
[email protected]898bbd32010-05-18 18:52:29170 return false;
171 }
172 } else {
[email protected]b7e899142010-06-02 17:03:32173 // The store ID was not specified; use the current execution context's
174 // cookie store by default.
[email protected]898bbd32010-05-18 18:52:29175 // GetCurrentBrowser() already takes into account incognito settings.
176 Browser* current_browser = GetCurrentBrowser();
177 if (!current_browser) {
178 error_ = keys::kNoCookieStoreFoundError;
179 return false;
180 }
181 store_profile = current_browser->profile();
[email protected]960927c02012-07-23 21:38:08182 *store_id = cookies_helpers::GetStoreIdFromProfile(store_profile);
[email protected]898bbd32010-05-18 18:52:29183 }
[email protected]9eaa18e2010-06-29 20:51:01184
185 if (context)
186 *context = store_profile->GetRequestContext();
[email protected]960927c02012-07-23 21:38:08187 DCHECK(context);
[email protected]9eaa18e2010-06-29 20:51:01188
[email protected]898bbd32010-05-18 18:52:29189 return true;
190}
191
[email protected]758b0b702013-01-10 12:19:33192GetCookieFunction::GetCookieFunction() {
[email protected]960927c02012-07-23 21:38:08193}
[email protected]9eaa18e2010-06-29 20:51:01194
[email protected]758b0b702013-01-10 12:19:33195GetCookieFunction::~GetCookieFunction() {
[email protected]960927c02012-07-23 21:38:08196}
[email protected]dec76e802010-09-23 22:43:53197
[email protected]758b0b702013-01-10 12:19:33198bool GetCookieFunction::RunImpl() {
[email protected]960927c02012-07-23 21:38:08199 parsed_args_ = Get::Params::Create(*args_);
200 EXTENSION_FUNCTION_VALIDATE(parsed_args_.get());
[email protected]898bbd32010-05-18 18:52:29201
202 // Read/validate input parameters.
[email protected]960927c02012-07-23 21:38:08203 if (!ParseUrl(parsed_args_->details.url, &url_, true))
[email protected]898bbd32010-05-18 18:52:29204 return false;
[email protected]898bbd32010-05-18 18:52:29205
[email protected]960927c02012-07-23 21:38:08206 std::string store_id = parsed_args_->details.store_id.get() ?
207 *parsed_args_->details.store_id : "";
[email protected]abe2c032011-03-31 18:49:34208 net::URLRequestContextGetter* store_context = NULL;
[email protected]960927c02012-07-23 21:38:08209 if (!ParseStoreContext(&store_id, &store_context))
[email protected]898bbd32010-05-18 18:52:29210 return false;
[email protected]960927c02012-07-23 21:38:08211 store_context_ = store_context;
212 if (!parsed_args_->details.store_id.get())
213 parsed_args_->details.store_id.reset(new std::string(store_id));
[email protected]898bbd32010-05-18 18:52:29214
[email protected]9eaa18e2010-06-29 20:51:01215 store_context_ = store_context;
216
[email protected]ca4b5fa32010-10-09 12:42:18217 bool rv = BrowserThread::PostTask(
218 BrowserThread::IO, FROM_HERE,
[email protected]758b0b702013-01-10 12:19:33219 base::Bind(&GetCookieFunction::GetCookieOnIOThread, this));
[email protected]9eaa18e2010-06-29 20:51:01220 DCHECK(rv);
221
222 // Will finish asynchronously.
223 return true;
224}
225
[email protected]758b0b702013-01-10 12:19:33226void GetCookieFunction::GetCookieOnIOThread() {
[email protected]ca4b5fa32010-10-09 12:42:18227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]277ec262011-03-30 21:09:40228 net::CookieStore* cookie_store =
229 store_context_->GetURLRequestContext()->cookie_store();
[email protected]92ba7b012012-05-16 03:36:17230 cookies_helpers::GetCookieListFromStore(
[email protected]b9e48094d2011-07-20 14:27:13231 cookie_store, url_,
[email protected]758b0b702013-01-10 12:19:33232 base::Bind(&GetCookieFunction::GetCookieCallback, this));
[email protected]b9e48094d2011-07-20 14:27:13233}
234
[email protected]758b0b702013-01-10 12:19:33235void GetCookieFunction::GetCookieCallback(const net::CookieList& cookie_list) {
[email protected]b9e48094d2011-07-20 14:27:13236 net::CookieList::const_iterator it;
[email protected]71c94e12011-02-17 09:46:07237 for (it = cookie_list.begin(); it != cookie_list.end(); ++it) {
[email protected]b7e899142010-06-02 17:03:32238 // Return the first matching cookie. Relies on the fact that the
[email protected]c58030202010-08-27 17:25:38239 // CookieMonster returns them in canonical order (longest path, then
240 // earliest creation time).
[email protected]960927c02012-07-23 21:38:08241 if (it->Name() == parsed_args_->details.name) {
242 scoped_ptr<Cookie> cookie(
243 cookies_helpers::CreateCookie(*it, *parsed_args_->details.store_id));
244 results_ = Get::Results::Create(*cookie);
[email protected]9eaa18e2010-06-29 20:51:01245 break;
[email protected]898bbd32010-05-18 18:52:29246 }
247 }
[email protected]9eaa18e2010-06-29 20:51:01248
[email protected]898bbd32010-05-18 18:52:29249 // The cookie doesn't exist; return null.
[email protected]71c94e12011-02-17 09:46:07250 if (it == cookie_list.end())
[email protected]07ff5fd2012-07-12 22:39:09251 SetResult(Value::CreateNullValue());
[email protected]9eaa18e2010-06-29 20:51:01252
[email protected]71c94e12011-02-17 09:46:07253 bool rv = BrowserThread::PostTask(
254 BrowserThread::UI, FROM_HERE,
[email protected]758b0b702013-01-10 12:19:33255 base::Bind(&GetCookieFunction::RespondOnUIThread, this));
[email protected]71c94e12011-02-17 09:46:07256 DCHECK(rv);
257}
258
[email protected]758b0b702013-01-10 12:19:33259void GetCookieFunction::RespondOnUIThread() {
[email protected]71c94e12011-02-17 09:46:07260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]9eaa18e2010-06-29 20:51:01261 SendResponse(true);
[email protected]898bbd32010-05-18 18:52:29262}
263
[email protected]758b0b702013-01-10 12:19:33264GetAllCookiesFunction::GetAllCookiesFunction() {
[email protected]960927c02012-07-23 21:38:08265}
[email protected]9eaa18e2010-06-29 20:51:01266
[email protected]758b0b702013-01-10 12:19:33267GetAllCookiesFunction::~GetAllCookiesFunction() {
[email protected]960927c02012-07-23 21:38:08268}
[email protected]dec76e802010-09-23 22:43:53269
[email protected]758b0b702013-01-10 12:19:33270bool GetAllCookiesFunction::RunImpl() {
[email protected]960927c02012-07-23 21:38:08271 parsed_args_ = GetAll::Params::Create(*args_);
272 EXTENSION_FUNCTION_VALIDATE(parsed_args_.get());
[email protected]e2d4bf02010-06-18 23:26:17273
[email protected]ccc91c62012-09-11 01:02:43274 if (parsed_args_->details.url.get() &&
275 !ParseUrl(*parsed_args_->details.url, &url_, false)) {
276 return false;
[email protected]960927c02012-07-23 21:38:08277 }
[email protected]34d18e42010-06-21 16:04:50278
[email protected]960927c02012-07-23 21:38:08279 std::string store_id = parsed_args_->details.store_id.get() ?
280 *parsed_args_->details.store_id : "";
[email protected]abe2c032011-03-31 18:49:34281 net::URLRequestContextGetter* store_context = NULL;
[email protected]960927c02012-07-23 21:38:08282 if (!ParseStoreContext(&store_id, &store_context))
[email protected]34d18e42010-06-21 16:04:50283 return false;
[email protected]9eaa18e2010-06-29 20:51:01284 store_context_ = store_context;
[email protected]960927c02012-07-23 21:38:08285 if (!parsed_args_->details.store_id.get())
286 parsed_args_->details.store_id.reset(new std::string(store_id));
[email protected]34d18e42010-06-21 16:04:50287
[email protected]ca4b5fa32010-10-09 12:42:18288 bool rv = BrowserThread::PostTask(
289 BrowserThread::IO, FROM_HERE,
[email protected]758b0b702013-01-10 12:19:33290 base::Bind(&GetAllCookiesFunction::GetAllCookiesOnIOThread, this));
[email protected]9eaa18e2010-06-29 20:51:01291 DCHECK(rv);
292
293 // Will finish asynchronously.
[email protected]34d18e42010-06-21 16:04:50294 return true;
[email protected]e2d4bf02010-06-18 23:26:17295}
296
[email protected]758b0b702013-01-10 12:19:33297void GetAllCookiesFunction::GetAllCookiesOnIOThread() {
[email protected]ca4b5fa32010-10-09 12:42:18298 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]277ec262011-03-30 21:09:40299 net::CookieStore* cookie_store =
300 store_context_->GetURLRequestContext()->cookie_store();
[email protected]92ba7b012012-05-16 03:36:17301 cookies_helpers::GetCookieListFromStore(
[email protected]b9e48094d2011-07-20 14:27:13302 cookie_store, url_,
[email protected]758b0b702013-01-10 12:19:33303 base::Bind(&GetAllCookiesFunction::GetAllCookiesCallback, this));
[email protected]b9e48094d2011-07-20 14:27:13304}
[email protected]9eaa18e2010-06-29 20:51:01305
[email protected]758b0b702013-01-10 12:19:33306void GetAllCookiesFunction::GetAllCookiesCallback(
[email protected]b9e48094d2011-07-20 14:27:13307 const net::CookieList& cookie_list) {
[email protected]1c321ee2012-05-21 03:02:34308 const extensions::Extension* extension = GetExtension();
[email protected]71c94e12011-02-17 09:46:07309 if (extension) {
[email protected]960927c02012-07-23 21:38:08310 std::vector<linked_ptr<Cookie> > match_vector;
311 cookies_helpers::AppendMatchingCookiesToVector(
312 cookie_list, url_, &parsed_args_->details,
313 GetExtension(), &match_vector);
314
315 results_ = GetAll::Results::Create(match_vector);
[email protected]71c94e12011-02-17 09:46:07316 }
[email protected]ca4b5fa32010-10-09 12:42:18317 bool rv = BrowserThread::PostTask(
318 BrowserThread::UI, FROM_HERE,
[email protected]758b0b702013-01-10 12:19:33319 base::Bind(&GetAllCookiesFunction::RespondOnUIThread, this));
[email protected]9eaa18e2010-06-29 20:51:01320 DCHECK(rv);
321}
322
[email protected]758b0b702013-01-10 12:19:33323void GetAllCookiesFunction::RespondOnUIThread() {
[email protected]ca4b5fa32010-10-09 12:42:18324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]9eaa18e2010-06-29 20:51:01325 SendResponse(true);
326}
327
[email protected]758b0b702013-01-10 12:19:33328SetCookieFunction::SetCookieFunction() : success_(false) {
[email protected]a6c8e72502010-07-24 09:18:25329}
[email protected]9eaa18e2010-06-29 20:51:01330
[email protected]758b0b702013-01-10 12:19:33331SetCookieFunction::~SetCookieFunction() {
[email protected]dec76e802010-09-23 22:43:53332}
333
[email protected]758b0b702013-01-10 12:19:33334bool SetCookieFunction::RunImpl() {
[email protected]960927c02012-07-23 21:38:08335 parsed_args_ = Set::Params::Create(*args_);
336 EXTENSION_FUNCTION_VALIDATE(parsed_args_.get());
[email protected]898bbd32010-05-18 18:52:29337
338 // Read/validate input parameters.
[email protected]960927c02012-07-23 21:38:08339 if (!ParseUrl(parsed_args_->details.url, &url_, true))
[email protected]898bbd32010-05-18 18:52:29340 return false;
[email protected]9eaa18e2010-06-29 20:51:01341
[email protected]960927c02012-07-23 21:38:08342 std::string store_id = parsed_args_->details.store_id.get() ?
343 *parsed_args_->details.store_id : "";
[email protected]abe2c032011-03-31 18:49:34344 net::URLRequestContextGetter* store_context = NULL;
[email protected]960927c02012-07-23 21:38:08345 if (!ParseStoreContext(&store_id, &store_context))
[email protected]898bbd32010-05-18 18:52:29346 return false;
[email protected]9eaa18e2010-06-29 20:51:01347 store_context_ = store_context;
[email protected]960927c02012-07-23 21:38:08348 if (!parsed_args_->details.store_id.get())
349 parsed_args_->details.store_id.reset(new std::string(store_id));
[email protected]898bbd32010-05-18 18:52:29350
[email protected]ca4b5fa32010-10-09 12:42:18351 bool rv = BrowserThread::PostTask(
352 BrowserThread::IO, FROM_HERE,
[email protected]758b0b702013-01-10 12:19:33353 base::Bind(&SetCookieFunction::SetCookieOnIOThread, this));
[email protected]9eaa18e2010-06-29 20:51:01354 DCHECK(rv);
355
356 // Will finish asynchronously.
[email protected]898bbd32010-05-18 18:52:29357 return true;
358}
359
[email protected]758b0b702013-01-10 12:19:33360void SetCookieFunction::SetCookieOnIOThread() {
[email protected]ca4b5fa32010-10-09 12:42:18361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]9eaa18e2010-06-29 20:51:01362 net::CookieMonster* cookie_monster =
[email protected]277ec262011-03-30 21:09:40363 store_context_->GetURLRequestContext()->cookie_store()->
364 GetCookieMonster();
[email protected]960927c02012-07-23 21:38:08365
366 base::Time expiration_time;
367 if (parsed_args_->details.expiration_date.get()) {
368 // Time::FromDoubleT converts double time 0 to empty Time object. So we need
369 // to do special handling here.
370 expiration_time = (*parsed_args_->details.expiration_date == 0) ?
371 base::Time::UnixEpoch() :
372 base::Time::FromDoubleT(*parsed_args_->details.expiration_date);
373 }
374
[email protected]b9e48094d2011-07-20 14:27:13375 cookie_monster->SetCookieWithDetailsAsync(
[email protected]960927c02012-07-23 21:38:08376 url_,
377 parsed_args_->details.name.get() ? *parsed_args_->details.name : "",
378 parsed_args_->details.value.get() ? *parsed_args_->details.value : "",
379 parsed_args_->details.domain.get() ? *parsed_args_->details.domain : "",
380 parsed_args_->details.path.get() ? *parsed_args_->details.path : "",
381 expiration_time,
382 parsed_args_->details.secure.get() ?
383 *parsed_args_->details.secure.get() :
384 false,
385 parsed_args_->details.http_only.get() ?
386 *parsed_args_->details.http_only :
387 false,
[email protected]758b0b702013-01-10 12:19:33388 base::Bind(&SetCookieFunction::PullCookie, this));
[email protected]b9e48094d2011-07-20 14:27:13389}
[email protected]9eaa18e2010-06-29 20:51:01390
[email protected]758b0b702013-01-10 12:19:33391void SetCookieFunction::PullCookie(bool set_cookie_result) {
[email protected]71c94e12011-02-17 09:46:07392 // Pull the newly set cookie.
[email protected]b9e48094d2011-07-20 14:27:13393 net::CookieMonster* cookie_monster =
394 store_context_->GetURLRequestContext()->cookie_store()->
395 GetCookieMonster();
396 success_ = set_cookie_result;
[email protected]92ba7b012012-05-16 03:36:17397 cookies_helpers::GetCookieListFromStore(
[email protected]b9e48094d2011-07-20 14:27:13398 cookie_monster, url_,
[email protected]758b0b702013-01-10 12:19:33399 base::Bind(&SetCookieFunction::PullCookieCallback, this));
[email protected]b9e48094d2011-07-20 14:27:13400}
401
[email protected]758b0b702013-01-10 12:19:33402void SetCookieFunction::PullCookieCallback(const net::CookieList& cookie_list) {
[email protected]b9e48094d2011-07-20 14:27:13403 net::CookieList::const_iterator it;
[email protected]71c94e12011-02-17 09:46:07404 for (it = cookie_list.begin(); it != cookie_list.end(); ++it) {
405 // Return the first matching cookie. Relies on the fact that the
406 // CookieMonster returns them in canonical order (longest path, then
407 // earliest creation time).
[email protected]960927c02012-07-23 21:38:08408 std::string name = parsed_args_->details.name.get() ?
409 *parsed_args_->details.name : "";
410 if (it->Name() == name) {
411 scoped_ptr<Cookie> cookie(
412 cookies_helpers::CreateCookie(*it, *parsed_args_->details.store_id));
413 results_ = Set::Results::Create(*cookie);
[email protected]71c94e12011-02-17 09:46:07414 break;
415 }
416 }
417
[email protected]ca4b5fa32010-10-09 12:42:18418 bool rv = BrowserThread::PostTask(
419 BrowserThread::UI, FROM_HERE,
[email protected]758b0b702013-01-10 12:19:33420 base::Bind(&SetCookieFunction::RespondOnUIThread, this));
[email protected]9eaa18e2010-06-29 20:51:01421 DCHECK(rv);
422}
423
[email protected]758b0b702013-01-10 12:19:33424void SetCookieFunction::RespondOnUIThread() {
[email protected]ca4b5fa32010-10-09 12:42:18425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]9eaa18e2010-06-29 20:51:01426 if (!success_) {
[email protected]960927c02012-07-23 21:38:08427 std::string name = parsed_args_->details.name.get() ?
428 *parsed_args_->details.name : "";
[email protected]e9f541a2012-11-19 21:52:31429 error_ = ErrorUtils::FormatErrorMessage(
[email protected]960927c02012-07-23 21:38:08430 keys::kCookieSetFailedError, name);
[email protected]9eaa18e2010-06-29 20:51:01431 }
432 SendResponse(success_);
433}
434
[email protected]758b0b702013-01-10 12:19:33435RemoveCookieFunction::RemoveCookieFunction() {
[email protected]b8290452011-03-21 14:11:14436}
[email protected]9eaa18e2010-06-29 20:51:01437
[email protected]758b0b702013-01-10 12:19:33438RemoveCookieFunction::~RemoveCookieFunction() {
[email protected]b8290452011-03-21 14:11:14439}
[email protected]9eaa18e2010-06-29 20:51:01440
[email protected]758b0b702013-01-10 12:19:33441bool RemoveCookieFunction::RunImpl() {
[email protected]960927c02012-07-23 21:38:08442 parsed_args_ = Remove::Params::Create(*args_);
443 EXTENSION_FUNCTION_VALIDATE(parsed_args_.get());
[email protected]898bbd32010-05-18 18:52:29444
445 // Read/validate input parameters.
[email protected]960927c02012-07-23 21:38:08446 if (!ParseUrl(parsed_args_->details.url, &url_, true))
[email protected]898bbd32010-05-18 18:52:29447 return false;
[email protected]898bbd32010-05-18 18:52:29448
[email protected]960927c02012-07-23 21:38:08449 std::string store_id = parsed_args_->details.store_id.get() ?
450 *parsed_args_->details.store_id : "";
[email protected]abe2c032011-03-31 18:49:34451 net::URLRequestContextGetter* store_context = NULL;
[email protected]960927c02012-07-23 21:38:08452 if (!ParseStoreContext(&store_id, &store_context))
[email protected]898bbd32010-05-18 18:52:29453 return false;
[email protected]b8290452011-03-21 14:11:14454 store_context_ = store_context;
[email protected]960927c02012-07-23 21:38:08455 if (!parsed_args_->details.store_id.get())
456 parsed_args_->details.store_id.reset(new std::string(store_id));
[email protected]898bbd32010-05-18 18:52:29457
[email protected]b8290452011-03-21 14:11:14458 // Pass the work off to the IO thread.
[email protected]ca4b5fa32010-10-09 12:42:18459 bool rv = BrowserThread::PostTask(
460 BrowserThread::IO, FROM_HERE,
[email protected]758b0b702013-01-10 12:19:33461 base::Bind(&RemoveCookieFunction::RemoveCookieOnIOThread, this));
[email protected]9eaa18e2010-06-29 20:51:01462 DCHECK(rv);
463
[email protected]b8290452011-03-21 14:11:14464 // Will return asynchronously.
[email protected]898bbd32010-05-18 18:52:29465 return true;
466}
467
[email protected]758b0b702013-01-10 12:19:33468void RemoveCookieFunction::RemoveCookieOnIOThread() {
[email protected]b8290452011-03-21 14:11:14469 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
470
471 // Remove the cookie
[email protected]277ec262011-03-30 21:09:40472 net::CookieStore* cookie_store =
473 store_context_->GetURLRequestContext()->cookie_store();
[email protected]b9e48094d2011-07-20 14:27:13474 cookie_store->DeleteCookieAsync(
[email protected]960927c02012-07-23 21:38:08475 url_, parsed_args_->details.name,
[email protected]758b0b702013-01-10 12:19:33476 base::Bind(&RemoveCookieFunction::RemoveCookieCallback, this));
[email protected]b9e48094d2011-07-20 14:27:13477}
[email protected]b8290452011-03-21 14:11:14478
[email protected]758b0b702013-01-10 12:19:33479void RemoveCookieFunction::RemoveCookieCallback() {
[email protected]b8290452011-03-21 14:11:14480 // Build the callback result
[email protected]960927c02012-07-23 21:38:08481 Remove::Results::Details details;
482 details.name = parsed_args_->details.name;
483 details.url = url_.spec();
484 details.store_id = *parsed_args_->details.store_id;
485 results_ = Remove::Results::Create(details);
[email protected]b8290452011-03-21 14:11:14486
487 // Return to UI thread
488 bool rv = BrowserThread::PostTask(
489 BrowserThread::UI, FROM_HERE,
[email protected]758b0b702013-01-10 12:19:33490 base::Bind(&RemoveCookieFunction::RespondOnUIThread, this));
[email protected]b8290452011-03-21 14:11:14491 DCHECK(rv);
492}
493
[email protected]758b0b702013-01-10 12:19:33494void RemoveCookieFunction::RespondOnUIThread() {
[email protected]b8290452011-03-21 14:11:14495 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
496 SendResponse(true);
[email protected]dec76e802010-09-23 22:43:53497}
498
[email protected]758b0b702013-01-10 12:19:33499bool GetAllCookieStoresFunction::RunImpl() {
[email protected]bc535ee52010-08-31 18:40:32500 Profile* original_profile = profile();
[email protected]898bbd32010-05-18 18:52:29501 DCHECK(original_profile);
502 scoped_ptr<ListValue> original_tab_ids(new ListValue());
503 Profile* incognito_profile = NULL;
504 scoped_ptr<ListValue> incognito_tab_ids;
[email protected]6df23c42010-12-15 08:52:57505 if (include_incognito() && profile()->HasOffTheRecordProfile()) {
[email protected]898bbd32010-05-18 18:52:29506 incognito_profile = profile()->GetOffTheRecordProfile();
507 if (incognito_profile)
508 incognito_tab_ids.reset(new ListValue());
509 }
[email protected]bc535ee52010-08-31 18:40:32510 DCHECK(original_profile != incognito_profile);
511
[email protected]b7e899142010-06-02 17:03:32512 // Iterate through all browser instances, and for each browser,
513 // add its tab IDs to either the regular or incognito tab ID list depending
514 // whether the browser is regular or incognito.
[email protected]898bbd32010-05-18 18:52:29515 for (BrowserList::const_iterator iter = BrowserList::begin();
516 iter != BrowserList::end(); ++iter) {
517 Browser* browser = *iter;
518 if (browser->profile() == original_profile) {
[email protected]960927c02012-07-23 21:38:08519 cookies_helpers::AppendToTabIdList(browser, original_tab_ids.get());
[email protected]898bbd32010-05-18 18:52:29520 } else if (incognito_tab_ids.get() &&
521 browser->profile() == incognito_profile) {
[email protected]960927c02012-07-23 21:38:08522 cookies_helpers::AppendToTabIdList(browser, incognito_tab_ids.get());
[email protected]898bbd32010-05-18 18:52:29523 }
524 }
[email protected]b7e899142010-06-02 17:03:32525 // Return a list of all cookie stores with at least one open tab.
[email protected]960927c02012-07-23 21:38:08526 std::vector<linked_ptr<CookieStore> > cookie_stores;
[email protected]898bbd32010-05-18 18:52:29527 if (original_tab_ids->GetSize() > 0) {
[email protected]960927c02012-07-23 21:38:08528 cookie_stores.push_back(make_linked_ptr(
529 cookies_helpers::CreateCookieStore(
530 original_profile, original_tab_ids.release()).release()));
[email protected]898bbd32010-05-18 18:52:29531 }
[email protected]f0a151f2011-07-08 22:26:15532 if (incognito_tab_ids.get() && incognito_tab_ids->GetSize() > 0 &&
533 incognito_profile) {
[email protected]960927c02012-07-23 21:38:08534 cookie_stores.push_back(make_linked_ptr(
535 cookies_helpers::CreateCookieStore(
536 incognito_profile, incognito_tab_ids.release()).release()));
[email protected]898bbd32010-05-18 18:52:29537 }
[email protected]960927c02012-07-23 21:38:08538 results_ = GetAllCookieStores::Results::Create(cookie_stores);
[email protected]898bbd32010-05-18 18:52:29539 return true;
540}
[email protected]dec76e802010-09-23 22:43:53541
[email protected]758b0b702013-01-10 12:19:33542void GetAllCookieStoresFunction::Run() {
[email protected]dec76e802010-09-23 22:43:53543 SendResponse(RunImpl());
544}
[email protected]92ba7b012012-05-16 03:36:17545
[email protected]c54115c2012-12-06 17:56:30546CookiesAPI::CookiesAPI(Profile* profile)
547 : profile_(profile) {
548 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
549 this, keys::kOnChanged);
550}
551
552CookiesAPI::~CookiesAPI() {
553}
554
555void CookiesAPI::Shutdown() {
556 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
557}
558
[email protected]c39df1a2013-01-08 18:22:07559static base::LazyInstance<ProfileKeyedAPIFactory<CookiesAPI> >
560g_factory = LAZY_INSTANCE_INITIALIZER;
561
562// static
563ProfileKeyedAPIFactory<CookiesAPI>* CookiesAPI::GetFactoryInstance() {
564 return &g_factory.Get();
565}
566
[email protected]c54115c2012-12-06 17:56:30567void CookiesAPI::OnListenerAdded(
568 const extensions::EventListenerInfo& details) {
569 cookies_event_router_.reset(new CookiesEventRouter(profile_));
570 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
571}
572
[email protected]92ba7b012012-05-16 03:36:17573} // namespace extensions