Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(674)

Side by Side Diff: chrome/browser/extensions/extension_cookies_api.cc

Issue 2860012: Revert 50296 (Causes DCHECK failures) - Make CookieMonster NonThreadSafe.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Implements the Chrome Extensions Cookies API. 5 // Implements the Chrome Extensions Cookies API.
6 6
7 #include "chrome/browser/extensions/extension_cookies_api.h" 7 #include "chrome/browser/extensions/extension_cookies_api.h"
8 8
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/task.h"
11 #include "chrome/browser/browser_list.h" 10 #include "chrome/browser/browser_list.h"
12 #include "chrome/browser/chrome_thread.h"
13 #include "chrome/browser/extensions/extension_cookies_api_constants.h" 11 #include "chrome/browser/extensions/extension_cookies_api_constants.h"
14 #include "chrome/browser/extensions/extension_cookies_helpers.h" 12 #include "chrome/browser/extensions/extension_cookies_helpers.h"
15 #include "chrome/browser/extensions/extension_message_service.h" 13 #include "chrome/browser/extensions/extension_message_service.h"
16 #include "chrome/browser/profile.h" 14 #include "chrome/browser/profile.h"
17 #include "chrome/common/extensions/extension_error_utils.h" 15 #include "chrome/common/extensions/extension_error_utils.h"
18 #include "chrome/common/net/url_request_context_getter.h" 16 #include "chrome/common/net/url_request_context_getter.h"
19 #include "chrome/common/notification_type.h" 17 #include "chrome/common/notification_type.h"
20 #include "chrome/common/notification_service.h" 18 #include "chrome/common/notification_service.h"
21 #include "net/base/cookie_monster.h" 19 #include "net/base/cookie_monster.h"
22 20
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 // Check against host permissions if needed. 92 // Check against host permissions if needed.
95 if (check_host_permissions && 93 if (check_host_permissions &&
96 !GetExtension()->HasHostPermission(*url)) { 94 !GetExtension()->HasHostPermission(*url)) {
97 error_ = ExtensionErrorUtils::FormatErrorMessage( 95 error_ = ExtensionErrorUtils::FormatErrorMessage(
98 keys::kNoHostPermissionsError, url->spec()); 96 keys::kNoHostPermissionsError, url->spec());
99 return false; 97 return false;
100 } 98 }
101 return true; 99 return true;
102 } 100 }
103 101
104 bool CookiesFunction::ParseStoreContext(const DictionaryValue* details, 102 bool CookiesFunction::ParseCookieStore(const DictionaryValue* details,
105 URLRequestContextGetter** context, 103 net::CookieStore** store,
106 std::string* store_id) { 104 std::string* store_id) {
107 DCHECK(details && (context || store_id)); 105 DCHECK(details && (store || store_id));
108 Profile* store_profile = NULL; 106 Profile* store_profile = NULL;
109 if (details->HasKey(keys::kStoreIdKey)) { 107 if (details->HasKey(keys::kStoreIdKey)) {
110 // The store ID was explicitly specified in the details dictionary. 108 // The store ID was explicitly specified in the details dictionary.
111 // Retrieve its corresponding cookie store. 109 // Retrieve its corresponding cookie store.
112 std::string store_id_value; 110 std::string store_id_value;
113 // Get the store ID string or return false. 111 // Get the store ID string or return false.
114 EXTENSION_FUNCTION_VALIDATE( 112 EXTENSION_FUNCTION_VALIDATE(
115 details->GetString(keys::kStoreIdKey, &store_id_value)); 113 details->GetString(keys::kStoreIdKey, &store_id_value));
116 store_profile = extension_cookies_helpers::ChooseProfileFromStoreId( 114 store_profile = extension_cookies_helpers::ChooseProfileFromStoreId(
117 store_id_value, profile(), include_incognito()); 115 store_id_value, profile(), include_incognito());
118 if (!store_profile) { 116 if (!store_profile) {
119 error_ = ExtensionErrorUtils::FormatErrorMessage( 117 error_ = ExtensionErrorUtils::FormatErrorMessage(
120 keys::kInvalidStoreIdError, store_id_value); 118 keys::kInvalidStoreIdError, store_id_value);
121 return false; 119 return false;
122 } 120 }
123 } else { 121 } else {
124 // The store ID was not specified; use the current execution context's 122 // The store ID was not specified; use the current execution context's
125 // cookie store by default. 123 // cookie store by default.
126 // GetCurrentBrowser() already takes into account incognito settings. 124 // GetCurrentBrowser() already takes into account incognito settings.
127 Browser* current_browser = GetCurrentBrowser(); 125 Browser* current_browser = GetCurrentBrowser();
128 if (!current_browser) { 126 if (!current_browser) {
129 error_ = keys::kNoCookieStoreFoundError; 127 error_ = keys::kNoCookieStoreFoundError;
130 return false; 128 return false;
131 } 129 }
132 store_profile = current_browser->profile(); 130 store_profile = current_browser->profile();
133 } 131 }
134 DCHECK(store_profile); 132 DCHECK(store_profile);
135 133 if (store)
136 if (context) 134 *store = store_profile->GetRequestContext()->GetCookieStore();
137 *context = store_profile->GetRequestContext();
138 if (store_id) 135 if (store_id)
139 *store_id = extension_cookies_helpers::GetStoreIdFromProfile(store_profile); 136 *store_id =
140 137 extension_cookies_helpers::GetStoreIdFromProfile(store_profile);
141 return true; 138 return true;
142 } 139 }
143 140
144 GetCookieFunction::GetCookieFunction() {}
145
146 bool GetCookieFunction::RunImpl() { 141 bool GetCookieFunction::RunImpl() {
147 // Return false if the arguments are malformed. 142 // Return false if the arguments are malformed.
148 DictionaryValue* details; 143 DictionaryValue* details;
149 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details)); 144 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
150 DCHECK(details); 145 DCHECK(details);
151 146
152 // Read/validate input parameters. 147 // Read/validate input parameters.
153 if (!ParseUrl(details, &url_, true)) 148 GURL url;
149 if (!ParseUrl(details, &url, true))
154 return false; 150 return false;
155 151
152 std::string name;
156 // Get the cookie name string or return false. 153 // Get the cookie name string or return false.
157 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name_)); 154 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name));
158 155
159 URLRequestContextGetter* store_context = NULL; 156 net::CookieStore* cookie_store;
160 if (!ParseStoreContext(details, &store_context, &store_id_)) 157 std::string store_id;
158 if (!ParseCookieStore(details, &cookie_store, &store_id))
161 return false; 159 return false;
160 DCHECK(cookie_store && !store_id.empty());
162 161
163 DCHECK(store_context && !store_id_.empty()); 162 net::CookieMonster::CookieList cookie_list =
164 store_context_ = store_context; 163 extension_cookies_helpers::GetCookieListFromStore(cookie_store, url);
165 164 net::CookieMonster::CookieList::iterator it;
166 bool rv = ChromeThread::PostTask( 165 for (it = cookie_list.begin(); it != cookie_list.end(); ++it) {
167 ChromeThread::IO, FROM_HERE, 166 // Return the first matching cookie. Relies on the fact that the
168 NewRunnableMethod(this, &GetCookieFunction::GetCookieOnIOThread)); 167 // CookieMonster retrieves them in reverse domain-length order.
169 DCHECK(rv); 168 const net::CookieMonster::CanonicalCookie& cookie = it->second;
170 169 if (cookie.Name() == name) {
171 // Will finish asynchronously. 170 result_.reset(
171 extension_cookies_helpers::CreateCookieValue(*it, store_id));
172 return true;
173 }
174 }
175 // The cookie doesn't exist; return null.
176 result_.reset(Value::CreateNullValue());
172 return true; 177 return true;
173 } 178 }
174 179
175 void GetCookieFunction::GetCookieOnIOThread() {
176 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
177 net::CookieStore* cookie_store = store_context_->GetCookieStore();
178 cookie_list_ =
179 extension_cookies_helpers::GetCookieListFromStore(cookie_store, url_);
180
181 bool rv = ChromeThread::PostTask(
182 ChromeThread::UI, FROM_HERE,
183 NewRunnableMethod(this, &GetCookieFunction::RespondOnUIThread));
184 DCHECK(rv);
185 }
186
187 void GetCookieFunction::RespondOnUIThread() {
188 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
189
190 net::CookieMonster::CookieList::iterator it;
191 for (it = cookie_list_.begin(); it != cookie_list_.end(); ++it) {
192 // Return the first matching cookie. Relies on the fact that the
193 // CookieMonster retrieves them in reverse domain-length order.
194 const net::CookieMonster::CanonicalCookie& cookie = it->second;
195 if (cookie.Name() == name_) {
196 result_.reset(
197 extension_cookies_helpers::CreateCookieValue(*it, store_id_));
198 break;
199 }
200 }
201
202 // The cookie doesn't exist; return null.
203 if (it == cookie_list_.end())
204 result_.reset(Value::CreateNullValue());
205
206 SendResponse(true);
207 }
208
209 GetAllCookiesFunction::GetAllCookiesFunction() {}
210
211 bool GetAllCookiesFunction::RunImpl() { 180 bool GetAllCookiesFunction::RunImpl() {
212 // Return false if the arguments are malformed. 181 // Return false if the arguments are malformed.
213 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details_)); 182 DictionaryValue* details;
214 DCHECK(details_); 183 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
184 DCHECK(details);
215 185
216 // Read/validate input parameters. 186 // Read/validate input parameters.
217 if (details_->HasKey(keys::kUrlKey) && !ParseUrl(details_, &url_, false)) 187 GURL url;
188 if (details->HasKey(keys::kUrlKey) && !ParseUrl(details, &url, false))
218 return false; 189 return false;
219 190
220 URLRequestContextGetter* store_context = NULL; 191 net::CookieStore* cookie_store;
221 if (!ParseStoreContext(details_, &store_context, &store_id_)) 192 std::string store_id;
193 if (!ParseCookieStore(details, &cookie_store, &store_id))
222 return false; 194 return false;
223 DCHECK(store_context); 195 DCHECK(cookie_store);
224 store_context_ = store_context;
225 196
226 bool rv = ChromeThread::PostTask( 197 ListValue* matching_list = new ListValue();
227 ChromeThread::IO, FROM_HERE, 198 extension_cookies_helpers::AppendMatchingCookiesToList(
228 NewRunnableMethod(this, &GetAllCookiesFunction::GetAllCookiesOnIOThread)); 199 cookie_store, store_id, url, details, GetExtension(), matching_list);
229 DCHECK(rv); 200 result_.reset(matching_list);
230
231 // Will finish asynchronously.
232 return true; 201 return true;
233 } 202 }
234 203
235 void GetAllCookiesFunction::GetAllCookiesOnIOThread() {
236 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
237 net::CookieStore* cookie_store = store_context_->GetCookieStore();
238 cookie_list_ =
239 extension_cookies_helpers::GetCookieListFromStore(cookie_store, url_);
240
241 bool rv = ChromeThread::PostTask(
242 ChromeThread::UI, FROM_HERE,
243 NewRunnableMethod(this, &GetAllCookiesFunction::RespondOnUIThread));
244 DCHECK(rv);
245 }
246
247 void GetAllCookiesFunction::RespondOnUIThread() {
248 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
249
250 const Extension* extension = GetExtension();
251 if (extension) {
252 ListValue* matching_list = new ListValue();
253 extension_cookies_helpers::AppendMatchingCookiesToList(
254 cookie_list_, store_id_, url_, details_, GetExtension(), matching_list);
255 result_.reset(matching_list);
256 }
257 SendResponse(true);
258 }
259
260 SetCookieFunction::SetCookieFunction() : secure_(false), http_only_(false) {}
261
262 bool SetCookieFunction::RunImpl() { 204 bool SetCookieFunction::RunImpl() {
263 // Return false if the arguments are malformed. 205 // Return false if the arguments are malformed.
264 DictionaryValue* details; 206 DictionaryValue* details;
265 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details)); 207 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
266 DCHECK(details); 208 DCHECK(details);
267 209
268 // Read/validate input parameters. 210 // Read/validate input parameters.
269 if (!ParseUrl(details, &url_, true)) 211 GURL url;
212 if (!ParseUrl(details, &url, true))
270 return false; 213 return false;
271 // The macros below return false if argument types are not as expected. 214 // The macros below return false if argument types are not as expected.
272 if (details->HasKey(keys::kNameKey)) 215 std::string name;
273 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name_)); 216 if (details->HasKey(keys::kNameKey)) {
274 if (details->HasKey(keys::kValueKey)) 217 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name));
275 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kValueKey, &value_)); 218 }
276 if (details->HasKey(keys::kDomainKey)) 219 std::string value;
277 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kDomainKey, &domain_)); 220 if (details->HasKey(keys::kValueKey)) {
278 if (details->HasKey(keys::kPathKey)) 221 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kValueKey, &value));
279 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kPathKey, &path_)); 222 }
280 223 std::string domain;
224 if (details->HasKey(keys::kDomainKey)) {
225 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kDomainKey, &domain));
226 }
227 std::string path;
228 if (details->HasKey(keys::kPathKey)) {
229 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kPathKey, &path));
230 }
231 bool secure = false;
281 if (details->HasKey(keys::kSecureKey)) { 232 if (details->HasKey(keys::kSecureKey)) {
282 EXTENSION_FUNCTION_VALIDATE( 233 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(keys::kSecureKey, &secure));
283 details->GetBoolean(keys::kSecureKey, &secure_));
284 } 234 }
235 bool http_only = false;
285 if (details->HasKey(keys::kHttpOnlyKey)) { 236 if (details->HasKey(keys::kHttpOnlyKey)) {
286 EXTENSION_FUNCTION_VALIDATE( 237 EXTENSION_FUNCTION_VALIDATE(
287 details->GetBoolean(keys::kHttpOnlyKey, &http_only_)); 238 details->GetBoolean(keys::kHttpOnlyKey, &http_only));
288 } 239 }
240 base::Time expiration_time;
289 if (details->HasKey(keys::kExpirationDateKey)) { 241 if (details->HasKey(keys::kExpirationDateKey)) {
290 Value* expiration_date_value; 242 Value* expiration_date_value;
291 EXTENSION_FUNCTION_VALIDATE(details->Get(keys::kExpirationDateKey, 243 EXTENSION_FUNCTION_VALIDATE(details->Get(keys::kExpirationDateKey,
292 &expiration_date_value)); 244 &expiration_date_value));
293 double expiration_date; 245 double expiration_date;
294 if (expiration_date_value->IsType(Value::TYPE_INTEGER)) { 246 if (expiration_date_value->IsType(Value::TYPE_INTEGER)) {
295 int expiration_date_int; 247 int expiration_date_int;
296 EXTENSION_FUNCTION_VALIDATE( 248 EXTENSION_FUNCTION_VALIDATE(
297 expiration_date_value->GetAsInteger(&expiration_date_int)); 249 expiration_date_value->GetAsInteger(&expiration_date_int));
298 expiration_date = static_cast<double>(expiration_date_int); 250 expiration_date = static_cast<double>(expiration_date_int);
299 } else { 251 } else {
300 EXTENSION_FUNCTION_VALIDATE( 252 EXTENSION_FUNCTION_VALIDATE(
301 expiration_date_value->GetAsReal(&expiration_date)); 253 expiration_date_value->GetAsReal(&expiration_date));
302 } 254 }
303 expiration_time_ = base::Time::FromDoubleT(expiration_date); 255 expiration_time = base::Time::FromDoubleT(expiration_date);
304 } 256 }
305 257
306 URLRequestContextGetter* store_context = NULL; 258 net::CookieStore* cookie_store;
307 if (!ParseStoreContext(details, &store_context, NULL)) 259 if (!ParseCookieStore(details, &cookie_store, NULL))
308 return false; 260 return false;
309 DCHECK(store_context); 261 DCHECK(cookie_store);
310 store_context_ = store_context;
311 262
312 bool rv = ChromeThread::PostTask( 263 if (!cookie_store->GetCookieMonster()->SetCookieWithDetails(
313 ChromeThread::IO, FROM_HERE, 264 url, name, value, domain, path, expiration_time, secure,
314 NewRunnableMethod(this, &SetCookieFunction::SetCookieOnIOThread)); 265 http_only)) {
315 DCHECK(rv); 266 error_ = ExtensionErrorUtils::FormatErrorMessage(
316 267 keys::kCookieSetFailedError, name);
317 // Will finish asynchronously. 268 return false;
269 }
318 return true; 270 return true;
319 } 271 }
320 272
321 void SetCookieFunction::SetCookieOnIOThread() {
322 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
323 net::CookieMonster* cookie_monster =
324 store_context_->GetCookieStore()->GetCookieMonster();
325 success_ = cookie_monster->SetCookieWithDetails(
326 url_, name_, value_, domain_, path_, expiration_time_,
327 secure_, http_only_);
328
329 bool rv = ChromeThread::PostTask(
330 ChromeThread::UI, FROM_HERE,
331 NewRunnableMethod(this, &SetCookieFunction::RespondOnUIThread));
332 DCHECK(rv);
333 }
334
335 void SetCookieFunction::RespondOnUIThread() {
336 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
337 if (!success_) {
338 error_ = ExtensionErrorUtils::FormatErrorMessage(
339 keys::kCookieSetFailedError, name_);
340 }
341 SendResponse(success_);
342 }
343
344 namespace {
345
346 class RemoveCookieTask : public Task {
347 public:
348 RemoveCookieTask(const GURL& url,
349 const std::string& name,
350 const scoped_refptr<URLRequestContextGetter>& context_getter)
351 : url_(url),
352 name_(name),
353 context_getter_(context_getter) {}
354
355 virtual void Run() {
356 net::CookieStore* cookie_store = context_getter_->GetCookieStore();
357 cookie_store->DeleteCookie(url_, name_);
358 }
359
360 private:
361 const GURL url_;
362 const std::string name_;
363 const scoped_refptr<URLRequestContextGetter> context_getter_;
364
365 DISALLOW_COPY_AND_ASSIGN(RemoveCookieTask);
366 };
367
368 } // namespace
369
370 bool RemoveCookieFunction::RunImpl() { 273 bool RemoveCookieFunction::RunImpl() {
371 // Return false if the arguments are malformed. 274 // Return false if the arguments are malformed.
372 DictionaryValue* details; 275 DictionaryValue* details;
373 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details)); 276 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
374 DCHECK(details); 277 DCHECK(details);
375 278
376 // Read/validate input parameters. 279 // Read/validate input parameters.
377 GURL url; 280 GURL url;
378 if (!ParseUrl(details, &url, true)) 281 if (!ParseUrl(details, &url, true))
379 return false; 282 return false;
380 283
381 std::string name; 284 std::string name;
382 // Get the cookie name string or return false. 285 // Get the cookie name string or return false.
383 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name)); 286 EXTENSION_FUNCTION_VALIDATE(details->GetString(keys::kNameKey, &name));
384 287
385 URLRequestContextGetter* store_context = NULL; 288 net::CookieStore* cookie_store;
386 if (!ParseStoreContext(details, &store_context, NULL)) 289 if (!ParseCookieStore(details, &cookie_store, NULL))
387 return false; 290 return false;
388 DCHECK(store_context); 291 DCHECK(cookie_store);
389 292
390 // We don't bother to synchronously wait for the result here, because 293 cookie_store->DeleteCookie(url, name);
391 // CookieMonster is only ever accessed on the IO thread, so any other accesses
392 // should happen after this.
393 bool rv = ChromeThread::PostTask(
394 ChromeThread::IO, FROM_HERE,
395 new RemoveCookieTask(url, name, store_context));
396 DCHECK(rv);
397
398 return true; 294 return true;
399 } 295 }
400 296
401 bool GetAllCookieStoresFunction::RunImpl() { 297 bool GetAllCookieStoresFunction::RunImpl() {
402 Profile* original_profile = profile()->GetOriginalProfile(); 298 Profile* original_profile = profile()->GetOriginalProfile();
403 DCHECK(original_profile); 299 DCHECK(original_profile);
404 scoped_ptr<ListValue> original_tab_ids(new ListValue()); 300 scoped_ptr<ListValue> original_tab_ids(new ListValue());
405 Profile* incognito_profile = NULL; 301 Profile* incognito_profile = NULL;
406 scoped_ptr<ListValue> incognito_tab_ids; 302 scoped_ptr<ListValue> incognito_tab_ids;
407 if (include_incognito()) { 303 if (include_incognito()) {
(...skipping 24 matching lines...) Expand all
432 original_profile, original_tab_ids.release())); 328 original_profile, original_tab_ids.release()));
433 } 329 }
434 if (incognito_tab_ids.get() && incognito_tab_ids->GetSize() > 0) { 330 if (incognito_tab_ids.get() && incognito_tab_ids->GetSize() > 0) {
435 cookie_store_list->Append( 331 cookie_store_list->Append(
436 extension_cookies_helpers::CreateCookieStoreValue( 332 extension_cookies_helpers::CreateCookieStoreValue(
437 incognito_profile, incognito_tab_ids.release())); 333 incognito_profile, incognito_tab_ids.release()));
438 } 334 }
439 result_.reset(cookie_store_list); 335 result_.reset(cookie_store_list);
440 return true; 336 return true;
441 } 337 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_cookies_api.h ('k') | chrome/browser/extensions/extension_cookies_helpers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698