| Index: chrome/browser/extensions/extension_cookies_api.cc
|
| diff --git a/chrome/browser/extensions/extension_cookies_api.cc b/chrome/browser/extensions/extension_cookies_api.cc
|
| index 0cf9b0741ca69433bcff304774f857debd824b82..1bf61c70816e7e5cdea2760fe10bbebcffbb980e 100644
|
| --- a/chrome/browser/extensions/extension_cookies_api.cc
|
| +++ b/chrome/browser/extensions/extension_cookies_api.cc
|
| @@ -7,7 +7,9 @@
|
| #include "chrome/browser/extensions/extension_cookies_api.h"
|
|
|
| #include "base/json/json_writer.h"
|
| +#include "base/task.h"
|
| #include "chrome/browser/browser_list.h"
|
| +#include "chrome/browser/chrome_thread.h"
|
| #include "chrome/browser/extensions/extension_cookies_api_constants.h"
|
| #include "chrome/browser/extensions/extension_cookies_helpers.h"
|
| #include "chrome/browser/extensions/extension_message_service.h"
|
| @@ -100,10 +102,10 @@ bool CookiesFunction::ParseUrl(const DictionaryValue* details, GURL* url,
|
| return true;
|
| }
|
|
|
| -bool CookiesFunction::ParseCookieStore(const DictionaryValue* details,
|
| - net::CookieStore** store,
|
| - std::string* store_id) {
|
| - DCHECK(details && (store || store_id));
|
| +bool CookiesFunction::ParseStoreContext(const DictionaryValue* details,
|
| + URLRequestContextGetter** context,
|
| + std::string* store_id) {
|
| + DCHECK(details && (context || store_id));
|
| Profile* store_profile = NULL;
|
| if (details->HasKey(keys::kStoreIdKey)) {
|
| // The store ID was explicitly specified in the details dictionary.
|
| @@ -131,14 +133,17 @@ bool CookiesFunction::ParseCookieStore(const DictionaryValue* details,
|
| store_profile = current_browser->profile();
|
| }
|
| DCHECK(store_profile);
|
| - if (store)
|
| - *store = store_profile->GetRequestContext()->GetCookieStore();
|
| +
|
| + if (context)
|
| + *context = store_profile->GetRequestContext();
|
| if (store_id)
|
| - *store_id =
|
| - extension_cookies_helpers::GetStoreIdFromProfile(store_profile);
|
| + *store_id = extension_cookies_helpers::GetStoreIdFromProfile(store_profile);
|
| +
|
| return true;
|
| }
|
|
|
| +GetCookieFunction::GetCookieFunction() {}
|
| +
|
| bool GetCookieFunction::RunImpl() {
|
| // Return false if the arguments are malformed.
|
| DictionaryValue* details;
|
| @@ -146,62 +151,115 @@ bool GetCookieFunction::RunImpl() {
|
| DCHECK(details);
|
|
|
| // Read/validate input parameters.
|
| - GURL url;
|
| - if (!ParseUrl(details, &url, true))
|
| + if (!ParseUrl(details, &url_, true))
|
| return false;
|
|
|
| - std::string name;
|
| // Get the cookie name string or return false.
|
| - EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name));
|
| + EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name_));
|
|
|
| - net::CookieStore* cookie_store;
|
| - std::string store_id;
|
| - if (!ParseCookieStore(details, &cookie_store, &store_id))
|
| + URLRequestContextGetter* store_context = NULL;
|
| + if (!ParseStoreContext(details, &store_context, &store_id_))
|
| return false;
|
| - DCHECK(cookie_store && !store_id.empty());
|
|
|
| - net::CookieMonster::CookieList cookie_list =
|
| - extension_cookies_helpers::GetCookieListFromStore(cookie_store, url);
|
| + DCHECK(store_context && !store_id_.empty());
|
| + store_context_ = store_context;
|
| +
|
| + bool rv = ChromeThread::PostTask(
|
| + ChromeThread::IO, FROM_HERE,
|
| + NewRunnableMethod(this, &GetCookieFunction::GetCookieOnIOThread));
|
| + DCHECK(rv);
|
| +
|
| + // Will finish asynchronously.
|
| + return true;
|
| +}
|
| +
|
| +void GetCookieFunction::GetCookieOnIOThread() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
|
| + net::CookieStore* cookie_store = store_context_->GetCookieStore();
|
| + cookie_list_ =
|
| + extension_cookies_helpers::GetCookieListFromStore(cookie_store, url_);
|
| +
|
| + bool rv = ChromeThread::PostTask(
|
| + ChromeThread::UI, FROM_HERE,
|
| + NewRunnableMethod(this, &GetCookieFunction::RespondOnUIThread));
|
| + DCHECK(rv);
|
| +}
|
| +
|
| +void GetCookieFunction::RespondOnUIThread() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
|
| +
|
| net::CookieMonster::CookieList::iterator it;
|
| - for (it = cookie_list.begin(); it != cookie_list.end(); ++it) {
|
| + for (it = cookie_list_.begin(); it != cookie_list_.end(); ++it) {
|
| // Return the first matching cookie. Relies on the fact that the
|
| // CookieMonster retrieves them in reverse domain-length order.
|
| const net::CookieMonster::CanonicalCookie& cookie = it->second;
|
| - if (cookie.Name() == name) {
|
| + if (cookie.Name() == name_) {
|
| result_.reset(
|
| - extension_cookies_helpers::CreateCookieValue(*it, store_id));
|
| - return true;
|
| + extension_cookies_helpers::CreateCookieValue(*it, store_id_));
|
| + break;
|
| }
|
| }
|
| +
|
| // The cookie doesn't exist; return null.
|
| - result_.reset(Value::CreateNullValue());
|
| - return true;
|
| + if (it == cookie_list_.end())
|
| + result_.reset(Value::CreateNullValue());
|
| +
|
| + SendResponse(true);
|
| }
|
|
|
| +GetAllCookiesFunction::GetAllCookiesFunction() {}
|
| +
|
| bool GetAllCookiesFunction::RunImpl() {
|
| // Return false if the arguments are malformed.
|
| - DictionaryValue* details;
|
| - EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
|
| - DCHECK(details);
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details_));
|
| + DCHECK(details_);
|
|
|
| // Read/validate input parameters.
|
| - GURL url;
|
| - if (details->HasKey(keys::kUrlKey) && !ParseUrl(details, &url, false))
|
| + if (details_->HasKey(keys::kUrlKey) && !ParseUrl(details_, &url_, false))
|
| return false;
|
|
|
| - net::CookieStore* cookie_store;
|
| - std::string store_id;
|
| - if (!ParseCookieStore(details, &cookie_store, &store_id))
|
| + URLRequestContextGetter* store_context = NULL;
|
| + if (!ParseStoreContext(details_, &store_context, &store_id_))
|
| return false;
|
| - DCHECK(cookie_store);
|
| + DCHECK(store_context);
|
| + store_context_ = store_context;
|
|
|
| - ListValue* matching_list = new ListValue();
|
| - extension_cookies_helpers::AppendMatchingCookiesToList(
|
| - cookie_store, store_id, url, details, GetExtension(), matching_list);
|
| - result_.reset(matching_list);
|
| + bool rv = ChromeThread::PostTask(
|
| + ChromeThread::IO, FROM_HERE,
|
| + NewRunnableMethod(this, &GetAllCookiesFunction::GetAllCookiesOnIOThread));
|
| + DCHECK(rv);
|
| +
|
| + // Will finish asynchronously.
|
| return true;
|
| }
|
|
|
| +void GetAllCookiesFunction::GetAllCookiesOnIOThread() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
|
| + net::CookieStore* cookie_store = store_context_->GetCookieStore();
|
| + cookie_list_ =
|
| + extension_cookies_helpers::GetCookieListFromStore(cookie_store, url_);
|
| +
|
| + bool rv = ChromeThread::PostTask(
|
| + ChromeThread::UI, FROM_HERE,
|
| + NewRunnableMethod(this, &GetAllCookiesFunction::RespondOnUIThread));
|
| + DCHECK(rv);
|
| +}
|
| +
|
| +void GetAllCookiesFunction::RespondOnUIThread() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
|
| +
|
| + const Extension* extension = GetExtension();
|
| + if (extension) {
|
| + ListValue* matching_list = new ListValue();
|
| + extension_cookies_helpers::AppendMatchingCookiesToList(
|
| + cookie_list_, store_id_, url_, details_, GetExtension(), matching_list);
|
| + result_.reset(matching_list);
|
| + }
|
| + SendResponse(true);
|
| +}
|
| +
|
| +SetCookieFunction::SetCookieFunction() : secure_(false), http_only_(false) {}
|
| +
|
| bool SetCookieFunction::RunImpl() {
|
| // Return false if the arguments are malformed.
|
| DictionaryValue* details;
|
| @@ -209,36 +267,26 @@ bool SetCookieFunction::RunImpl() {
|
| DCHECK(details);
|
|
|
| // Read/validate input parameters.
|
| - GURL url;
|
| - if (!ParseUrl(details, &url, true))
|
| + if (!ParseUrl(details, &url_, true))
|
| return false;
|
| // The macros below return false if argument types are not as expected.
|
| - std::string name;
|
| - if (details->HasKey(keys::kNameKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name));
|
| - }
|
| - std::string value;
|
| - if (details->HasKey(keys::kValueKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kValueKey, &value));
|
| - }
|
| - std::string domain;
|
| - if (details->HasKey(keys::kDomainKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kDomainKey, &domain));
|
| - }
|
| - std::string path;
|
| - if (details->HasKey(keys::kPathKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kPathKey, &path));
|
| - }
|
| - bool secure = false;
|
| + if (details->HasKey(keys::kNameKey))
|
| + EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name_));
|
| + if (details->HasKey(keys::kValueKey))
|
| + EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kValueKey, &value_));
|
| + if (details->HasKey(keys::kDomainKey))
|
| + EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kDomainKey, &domain_));
|
| + if (details->HasKey(keys::kPathKey))
|
| + EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kPathKey, &path_));
|
| +
|
| if (details->HasKey(keys::kSecureKey)) {
|
| - EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(keys::kSecureKey, &secure));
|
| + EXTENSION_FUNCTION_VALIDATE(
|
| + details->GetBoolean(keys::kSecureKey, &secure_));
|
| }
|
| - bool http_only = false;
|
| if (details->HasKey(keys::kHttpOnlyKey)) {
|
| EXTENSION_FUNCTION_VALIDATE(
|
| - details->GetBoolean(keys::kHttpOnlyKey, &http_only));
|
| + details->GetBoolean(keys::kHttpOnlyKey, &http_only_));
|
| }
|
| - base::Time expiration_time;
|
| if (details->HasKey(keys::kExpirationDateKey)) {
|
| Value* expiration_date_value;
|
| EXTENSION_FUNCTION_VALIDATE(details->Get(keys::kExpirationDateKey,
|
| @@ -253,24 +301,73 @@ bool SetCookieFunction::RunImpl() {
|
| EXTENSION_FUNCTION_VALIDATE(
|
| expiration_date_value->GetAsReal(&expiration_date));
|
| }
|
| - expiration_time = base::Time::FromDoubleT(expiration_date);
|
| + expiration_time_ = base::Time::FromDoubleT(expiration_date);
|
| }
|
|
|
| - net::CookieStore* cookie_store;
|
| - if (!ParseCookieStore(details, &cookie_store, NULL))
|
| + URLRequestContextGetter* store_context = NULL;
|
| + if (!ParseStoreContext(details, &store_context, NULL))
|
| return false;
|
| - DCHECK(cookie_store);
|
| + DCHECK(store_context);
|
| + store_context_ = store_context;
|
| +
|
| + bool rv = ChromeThread::PostTask(
|
| + ChromeThread::IO, FROM_HERE,
|
| + NewRunnableMethod(this, &SetCookieFunction::SetCookieOnIOThread));
|
| + DCHECK(rv);
|
|
|
| - if (!cookie_store->GetCookieMonster()->SetCookieWithDetails(
|
| - url, name, value, domain, path, expiration_time, secure,
|
| - http_only)) {
|
| + // Will finish asynchronously.
|
| + return true;
|
| +}
|
| +
|
| +void SetCookieFunction::SetCookieOnIOThread() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
|
| + net::CookieMonster* cookie_monster =
|
| + store_context_->GetCookieStore()->GetCookieMonster();
|
| + success_ = cookie_monster->SetCookieWithDetails(
|
| + url_, name_, value_, domain_, path_, expiration_time_,
|
| + secure_, http_only_);
|
| +
|
| + bool rv = ChromeThread::PostTask(
|
| + ChromeThread::UI, FROM_HERE,
|
| + NewRunnableMethod(this, &SetCookieFunction::RespondOnUIThread));
|
| + DCHECK(rv);
|
| +}
|
| +
|
| +void SetCookieFunction::RespondOnUIThread() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
|
| + if (!success_) {
|
| error_ = ExtensionErrorUtils::FormatErrorMessage(
|
| - keys::kCookieSetFailedError, name);
|
| - return false;
|
| + keys::kCookieSetFailedError, name_);
|
| }
|
| - return true;
|
| + SendResponse(success_);
|
| }
|
|
|
| +namespace {
|
| +
|
| +class RemoveCookieTask : public Task {
|
| + public:
|
| + RemoveCookieTask(const GURL& url,
|
| + const std::string& name,
|
| + const scoped_refptr<URLRequestContextGetter>& context_getter)
|
| + : url_(url),
|
| + name_(name),
|
| + context_getter_(context_getter) {}
|
| +
|
| + virtual void Run() {
|
| + net::CookieStore* cookie_store = context_getter_->GetCookieStore();
|
| + cookie_store->DeleteCookie(url_, name_);
|
| + }
|
| +
|
| + private:
|
| + const GURL url_;
|
| + const std::string name_;
|
| + const scoped_refptr<URLRequestContextGetter> context_getter_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(RemoveCookieTask);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| bool RemoveCookieFunction::RunImpl() {
|
| // Return false if the arguments are malformed.
|
| DictionaryValue* details;
|
| @@ -286,12 +383,19 @@ bool RemoveCookieFunction::RunImpl() {
|
| // Get the cookie name string or return false.
|
| EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name));
|
|
|
| - net::CookieStore* cookie_store;
|
| - if (!ParseCookieStore(details, &cookie_store, NULL))
|
| + URLRequestContextGetter* store_context = NULL;
|
| + if (!ParseStoreContext(details, &store_context, NULL))
|
| return false;
|
| - DCHECK(cookie_store);
|
| + DCHECK(store_context);
|
| +
|
| + // We don't bother to synchronously wait for the result here, because
|
| + // CookieMonster is only ever accessed on the IO thread, so any other accesses
|
| + // should happen after this.
|
| + bool rv = ChromeThread::PostTask(
|
| + ChromeThread::IO, FROM_HERE,
|
| + new RemoveCookieTask(url, name, store_context));
|
| + DCHECK(rv);
|
|
|
| - cookie_store->DeleteCookie(url, name);
|
| return true;
|
| }
|
|
|
|
|