OLD | NEW |
---|---|
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 |
OLD | NEW |