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

Side by Side Diff: chrome/browser/extensions/api/cookies/cookies_helpers.cc

Issue 10702088: Refactor chrome.cookies API to use JSON schema compiler. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Cookies helpers, unit tests, other nits Created 8 years, 5 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 common functionality for the Chrome Extensions Cookies API. 5 // Implements common functionality for the Chrome Extensions Cookies API.
6 6
7 #include "chrome/browser/extensions/api/cookies/cookies_helpers.h" 7 #include "chrome/browser/extensions/api/cookies/cookies_helpers.h"
8 8
9 #include <vector>
10
9 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/linked_ptr.h"
10 #include "base/string_util.h" 13 #include "base/string_util.h"
11 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
12 #include "base/values.h" 15 #include "base/values.h"
13 #include "chrome/browser/extensions/api/cookies/cookies_api_constants.h" 16 #include "chrome/browser/extensions/api/cookies/cookies_api_constants.h"
14 #include "chrome/browser/extensions/extension_tab_util.h" 17 #include "chrome/browser/extensions/extension_tab_util.h"
15 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser.h" 19 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/tab_contents/tab_contents.h" 20 #include "chrome/browser/ui/tab_contents/tab_contents.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h" 21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
22 #include "chrome/common/extensions/api/cookies.h"
19 #include "chrome/common/extensions/extension.h" 23 #include "chrome/common/extensions/extension.h"
20 #include "chrome/common/url_constants.h" 24 #include "chrome/common/url_constants.h"
21 #include "content/public/browser/web_contents.h" 25 #include "content/public/browser/web_contents.h"
22 #include "googleurl/src/gurl.h" 26 #include "googleurl/src/gurl.h"
23 #include "net/cookies/cookie_util.h" 27 #include "net/cookies/cookie_util.h"
24 28
29 using extensions::api::cookies::Cookie;
30 using extensions::api::cookies::CookieStore;
31
32 namespace GetAll = extensions::api::cookies::GetAll;
33
25 namespace extensions { 34 namespace extensions {
26 35
27 namespace keys = cookies_api_constants; 36 namespace keys = cookies_api_constants;
28 37
29 namespace cookies_helpers { 38 namespace cookies_helpers {
30 39
31 static const char kOriginalProfileStoreId[] = "0"; 40 static const char kOriginalProfileStoreId[] = "0";
32 static const char kOffTheRecordProfileStoreId[] = "1"; 41 static const char kOffTheRecordProfileStoreId[] = "1";
33 42
34 Profile* ChooseProfileFromStoreId(const std::string& store_id, 43 Profile* ChooseProfileFromStoreId(const std::string& store_id,
35 Profile* profile, 44 Profile* profile,
36 bool include_incognito) { 45 bool include_incognito) {
37 DCHECK(profile); 46 DCHECK(profile);
38 bool allow_original = !profile->IsOffTheRecord(); 47 bool allow_original = !profile->IsOffTheRecord();
39 bool allow_incognito = profile->IsOffTheRecord() || 48 bool allow_incognito = profile->IsOffTheRecord() ||
40 (include_incognito && profile->HasOffTheRecordProfile()); 49 (include_incognito && profile->HasOffTheRecordProfile());
41 if (store_id == kOriginalProfileStoreId && allow_original) 50 if (store_id == kOriginalProfileStoreId && allow_original)
42 return profile->GetOriginalProfile(); 51 return profile->GetOriginalProfile();
43 if (store_id == kOffTheRecordProfileStoreId && allow_incognito) 52 if (store_id == kOffTheRecordProfileStoreId && allow_incognito)
44 return profile->GetOffTheRecordProfile(); 53 return profile->GetOffTheRecordProfile();
45 return NULL; 54 return NULL;
46 } 55 }
47 56
48 const char* GetStoreIdFromProfile(Profile* profile) { 57 const char* GetStoreIdFromProfile(Profile* profile) {
49 DCHECK(profile); 58 DCHECK(profile);
50 return profile->IsOffTheRecord() ? 59 return profile->IsOffTheRecord() ?
51 kOffTheRecordProfileStoreId : kOriginalProfileStoreId; 60 kOffTheRecordProfileStoreId : kOriginalProfileStoreId;
52 } 61 }
53 62
54 DictionaryValue* CreateCookieValue( 63 Cookie* CreateCookie(
55 const net::CookieMonster::CanonicalCookie& cookie, 64 const net::CookieMonster::CanonicalCookie& cookie,
56 const std::string& store_id) { 65 const std::string& store_id) {
57 DictionaryValue* result = new DictionaryValue(); 66 DictionaryValue dict;
58 67
59 // A cookie is a raw byte sequence. By explicitly parsing it as UTF8, we 68 // A cookie is a raw byte sequence. By explicitly parsing it as UTF8, we
60 // apply error correction, so the string can be safely passed to the 69 // apply error correction, so the string can be safely passed to the
61 // renderer. 70 // renderer.
62 result->SetString(keys::kNameKey, UTF8ToUTF16(cookie.Name())); 71 dict.SetString(keys::kNameKey, UTF8ToUTF16(cookie.Name()));
Aaron Boodman 2012/07/09 17:34:49 Is it possible to just populate new_cookie directl
mitchellwrosen 2012/07/09 19:36:12 Done for populating a Cookie, but I think it may b
63 result->SetString(keys::kValueKey, UTF8ToUTF16(cookie.Value())); 72 dict.SetString(keys::kValueKey, UTF8ToUTF16(cookie.Value()));
64 result->SetString(keys::kDomainKey, cookie.Domain()); 73 dict.SetString(keys::kDomainKey, cookie.Domain());
65 result->SetBoolean(keys::kHostOnlyKey, 74 dict.SetBoolean(keys::kHostOnlyKey,
66 net::cookie_util::DomainIsHostOnly(cookie.Domain())); 75 net::cookie_util::DomainIsHostOnly(cookie.Domain()));
67 76
68 // A non-UTF8 path is invalid, so we just replace it with an empty string. 77 // A non-UTF8 path is invalid, so we just replace it with an empty string.
69 result->SetString(keys::kPathKey, 78 dict.SetString(keys::kPathKey,
70 IsStringUTF8(cookie.Path()) ? cookie.Path() : ""); 79 IsStringUTF8(cookie.Path()) ? cookie.Path() : "");
71 result->SetBoolean(keys::kSecureKey, cookie.IsSecure()); 80 dict.SetBoolean(keys::kSecureKey, cookie.IsSecure());
72 result->SetBoolean(keys::kHttpOnlyKey, cookie.IsHttpOnly()); 81 dict.SetBoolean(keys::kHttpOnlyKey, cookie.IsHttpOnly());
73 result->SetBoolean(keys::kSessionKey, !cookie.DoesExpire()); 82 dict.SetBoolean(keys::kSessionKey, !cookie.DoesExpire());
74 if (cookie.DoesExpire()) { 83 if (cookie.DoesExpire())
75 result->SetDouble(keys::kExpirationDateKey, 84 dict.SetDouble(keys::kExpirationDateKey, cookie.ExpiryDate().ToDoubleT());
76 cookie.ExpiryDate().ToDoubleT()); 85 dict.SetString(keys::kStoreIdKey, store_id);
77 }
78 result->SetString(keys::kStoreIdKey, store_id);
79 86
80 return result; 87 Cookie* new_cookie = new Cookie();
88 bool rv = Cookie::Populate(dict, new_cookie);
89 CHECK(rv);
90 return new_cookie;
81 } 91 }
82 92
83 DictionaryValue* CreateCookieStoreValue(Profile* profile, 93 CookieStore* CreateCookieStore(Profile* profile, ListValue* tab_ids) {
84 ListValue* tab_ids) {
85 DCHECK(profile); 94 DCHECK(profile);
86 DCHECK(tab_ids); 95 DCHECK(tab_ids);
87 DictionaryValue* result = new DictionaryValue(); 96 DictionaryValue dict;
88 result->SetString(keys::kIdKey, GetStoreIdFromProfile(profile)); 97 dict.SetString(keys::kIdKey, GetStoreIdFromProfile(profile));
89 result->Set(keys::kTabIdsKey, tab_ids); 98 dict.Set(keys::kTabIdsKey, tab_ids);
90 return result; 99
100 CookieStore* cookie_store = new CookieStore();
101 bool rv = CookieStore::Populate(dict, cookie_store);
102 CHECK(rv);
103 return cookie_store;
91 } 104 }
92 105
93 void GetCookieListFromStore( 106 void GetCookieListFromStore(
94 net::CookieStore* cookie_store, const GURL& url, 107 net::CookieStore* cookie_store, const GURL& url,
95 const net::CookieMonster::GetCookieListCallback& callback) { 108 const net::CookieMonster::GetCookieListCallback& callback) {
96 DCHECK(cookie_store); 109 DCHECK(cookie_store);
97 net::CookieMonster* monster = cookie_store->GetCookieMonster(); 110 net::CookieMonster* monster = cookie_store->GetCookieMonster();
98 if (!url.is_empty()) { 111 if (!url.is_empty()) {
99 DCHECK(url.is_valid()); 112 DCHECK(url.is_valid());
100 monster->GetAllCookiesForURLAsync(url, callback); 113 monster->GetAllCookiesForURLAsync(url, callback);
101 } else { 114 } else {
102 monster->GetAllCookiesAsync(callback); 115 monster->GetAllCookiesAsync(callback);
103 } 116 }
104 } 117 }
105 118
106 GURL GetURLFromCanonicalCookie( 119 GURL GetURLFromCanonicalCookie(
107 const net::CookieMonster::CanonicalCookie& cookie) { 120 const net::CookieMonster::CanonicalCookie& cookie) {
108 const std::string& domain_key = cookie.Domain(); 121 const std::string& domain_key = cookie.Domain();
109 const std::string scheme = 122 const std::string scheme =
110 cookie.IsSecure() ? chrome::kHttpsScheme : chrome::kHttpScheme; 123 cookie.IsSecure() ? chrome::kHttpsScheme : chrome::kHttpScheme;
111 const std::string host = 124 const std::string host =
112 domain_key.find('.') != 0 ? domain_key : domain_key.substr(1); 125 domain_key.find('.') != 0 ? domain_key : domain_key.substr(1);
113 return GURL(scheme + content::kStandardSchemeSeparator + host + "/"); 126 return GURL(scheme + content::kStandardSchemeSeparator + host + "/");
114 } 127 }
115 128
116 void AppendMatchingCookiesToList( 129 void AppendMatchingCookiesToVector(
117 const net::CookieList& all_cookies, 130 const net::CookieList& all_cookies,
118 const std::string& store_id, 131 const GURL& url, const GetAll::Params::Details* details,
119 const GURL& url, const DictionaryValue* details,
120 const Extension* extension, 132 const Extension* extension,
121 ListValue* match_list) { 133 std::vector<linked_ptr<Cookie> >* match_vector) {
122 net::CookieList::const_iterator it; 134 net::CookieList::const_iterator it;
123 for (it = all_cookies.begin(); it != all_cookies.end(); ++it) { 135 for (it = all_cookies.begin(); it != all_cookies.end(); ++it) {
124 // Ignore any cookie whose domain doesn't match the extension's 136 // Ignore any cookie whose domain doesn't match the extension's
125 // host permissions. 137 // host permissions.
126 GURL cookie_domain_url = GetURLFromCanonicalCookie(*it); 138 GURL cookie_domain_url = GetURLFromCanonicalCookie(*it);
127 if (!extension->HasHostPermission(cookie_domain_url)) 139 if (!extension->HasHostPermission(cookie_domain_url))
128 continue; 140 continue;
129 // Filter the cookie using the match filter. 141 // Filter the cookie using the match filter.
130 cookies_helpers::MatchFilter filter(details); 142 cookies_helpers::MatchFilter filter(details);
131 if (filter.MatchesCookie(*it)) 143 if (filter.MatchesCookie(*it)) {
132 match_list->Append(CreateCookieValue(*it, store_id)); 144 linked_ptr<Cookie> cookie(CreateCookie(*it, *details->store_id));
Aaron Boodman 2012/07/09 17:34:49 Since you don't need the local, you could use make
mitchellwrosen 2012/07/09 19:36:12 Done.
145 match_vector->push_back(cookie);
146 }
133 } 147 }
134 } 148 }
135 149
136 void AppendToTabIdList(Browser* browser, ListValue* tab_ids) { 150 void AppendToTabIdList(Browser* browser, ListValue* tab_ids) {
137 DCHECK(browser); 151 DCHECK(browser);
138 DCHECK(tab_ids); 152 DCHECK(tab_ids);
139 TabStripModel* tab_strip = browser->tab_strip_model(); 153 TabStripModel* tab_strip = browser->tab_strip_model();
140 for (int i = 0; i < tab_strip->count(); ++i) { 154 for (int i = 0; i < tab_strip->count(); ++i) {
141 tab_ids->Append(Value::CreateIntegerValue( 155 tab_ids->Append(Value::CreateIntegerValue(
142 ExtensionTabUtil::GetTabId( 156 ExtensionTabUtil::GetTabId(
143 tab_strip->GetTabContentsAt(i)->web_contents()))); 157 tab_strip->GetTabContentsAt(i)->web_contents())));
144 } 158 }
145 } 159 }
146 160
147 MatchFilter::MatchFilter(const DictionaryValue* details) 161 MatchFilter::MatchFilter(const GetAll::Params::Details* details)
148 : details_(details) { 162 : details_(details) {
149 DCHECK(details_); 163 DCHECK(details_);
150 } 164 }
151 165
152 bool MatchFilter::MatchesCookie( 166 bool MatchFilter::MatchesCookie(
153 const net::CookieMonster::CanonicalCookie& cookie) { 167 const net::CookieMonster::CanonicalCookie& cookie) {
154 return MatchesString(keys::kNameKey, cookie.Name()) && 168 bool matchesName = !details_->name.get() || *details_->name == cookie.Name();
Aaron Boodman 2012/07/09 17:34:49 Consider restructuring this logic like: if (detai
mitchellwrosen 2012/07/09 19:36:12 Done.
155 MatchesDomain(cookie.Domain()) && 169 bool matchesDomain = MatchesDomain(cookie.Domain());
156 MatchesString(keys::kPathKey, cookie.Path()) && 170 bool matchesPath = !details_->path.get() || *details_->path == cookie.Path();
157 MatchesBoolean(keys::kSecureKey, cookie.IsSecure()) && 171 bool matchesSecure = !details_->secure.get() ||
158 MatchesBoolean(keys::kSessionKey, !cookie.DoesExpire()); 172 *details_->secure == cookie.IsSecure();
159 } 173 bool matchesSession = !details_->session.get() ||
174 *details_->session == !cookie.DoesExpire();
160 175
161 bool MatchFilter::MatchesString(const char* key, const std::string& value) { 176 return matchesName && matchesDomain && matchesPath && matchesSecure &&
162 if (!details_->HasKey(key)) 177 matchesSession;
163 return true;
164 std::string filter_value;
165 return (details_->GetString(key, &filter_value) &&
166 value == filter_value);
167 }
168
169 bool MatchFilter::MatchesBoolean(const char* key, bool value) {
170 if (!details_->HasKey(key))
171 return true;
172 bool filter_value = false;
173 return (details_->GetBoolean(key, &filter_value) &&
174 value == filter_value);
175 } 178 }
176 179
177 bool MatchFilter::MatchesDomain(const std::string& domain) { 180 bool MatchFilter::MatchesDomain(const std::string& domain) {
178 if (!details_->HasKey(keys::kDomainKey)) 181 if (!details_->domain.get())
179 return true; 182 return true;
180 183
181 std::string filter_value;
182 if (!details_->GetString(keys::kDomainKey, &filter_value))
183 return false;
184 // Add a leading '.' character to the filter domain if it doesn't exist. 184 // Add a leading '.' character to the filter domain if it doesn't exist.
185 if (net::cookie_util::DomainIsHostOnly(filter_value)) 185 if (net::cookie_util::DomainIsHostOnly(*details_->domain))
186 filter_value.insert(0, "."); 186 details_->domain->insert(0, ".");
187 187
188 std::string sub_domain(domain); 188 std::string sub_domain(domain);
189 // Strip any leading '.' character from the input cookie domain. 189 // Strip any leading '.' character from the input cookie domain.
190 if (!net::cookie_util::DomainIsHostOnly(sub_domain)) 190 if (!net::cookie_util::DomainIsHostOnly(sub_domain))
191 sub_domain = sub_domain.substr(1); 191 sub_domain = sub_domain.substr(1);
192 192
193 // Now check whether the domain argument is a subdomain of the filter domain. 193 // Now check whether the domain argument is a subdomain of the filter domain.
194 for (sub_domain.insert(0, "."); 194 for (sub_domain.insert(0, ".");
195 sub_domain.length() >= filter_value.length();) { 195 sub_domain.length() >= details_->domain->length();) {
196 if (sub_domain == filter_value) 196 if (sub_domain == *details_->domain)
197 return true; 197 return true;
198 const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot. 198 const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot.
199 sub_domain.erase(0, next_dot); 199 sub_domain.erase(0, next_dot);
200 } 200 }
201 return false; 201 return false;
202 } 202 }
203 203
204 } // namespace cookies_helpers 204 } // namespace cookies_helpers
205 } // namespace extension 205 } // namespace extension
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698