Chromium Code Reviews| 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 |