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; |
} |