diff options
Diffstat (limited to 'chrome/browser/extensions/extension_cookies_helpers.cc')
-rw-r--r-- | chrome/browser/extensions/extension_cookies_helpers.cc | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/chrome/browser/extensions/extension_cookies_helpers.cc b/chrome/browser/extensions/extension_cookies_helpers.cc new file mode 100644 index 0000000..2322c1d --- /dev/null +++ b/chrome/browser/extensions/extension_cookies_helpers.cc @@ -0,0 +1,182 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Implements common functionality for the Chrome Extensions Cookies API. + +#include "chrome/browser/extensions/extension_cookies_helpers.h" + +#include "base/logging.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/extensions/extension_cookies_api_constants.h" +#include "chrome/browser/extensions/extension_tabs_module.h" +#include "chrome/browser/profile.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/url_constants.h" +#include "googleurl/src/gurl.h" + +namespace keys = extension_cookies_api_constants; + +namespace extension_cookies_helpers { + +static const char kOriginalProfileStoreId[] = "0"; +static const char kOffTheRecordProfileStoreId[] = "1"; + +Profile* ChooseProfileFromStoreId(const std::string& store_id, + Profile* profile, + bool include_incognito) { + DCHECK(profile); + if (store_id == kOriginalProfileStoreId) + return profile->GetOriginalProfile(); + if (store_id == kOffTheRecordProfileStoreId && include_incognito) + return profile->GetOffTheRecordProfile(); + return NULL; +} + +const char* GetStoreIdFromProfile(Profile* profile) { + DCHECK(profile); + return profile->IsOffTheRecord() ? + kOffTheRecordProfileStoreId : kOriginalProfileStoreId; +} + +DictionaryValue* CreateCookieValue( + const net::CookieMonster::CanonicalCookie& cookie, + const std::string& store_id) { + DictionaryValue* result = new DictionaryValue(); + + result->SetString(keys::kNameKey, cookie.Name()); + result->SetString(keys::kValueKey, cookie.Value()); + result->SetString(keys::kDomainKey, cookie.Domain()); + result->SetBoolean(keys::kHostOnlyKey, + net::CookieMonster::DomainIsHostOnly(cookie.Domain())); + result->SetString(keys::kPathKey, cookie.Path()); + result->SetBoolean(keys::kSecureKey, cookie.IsSecure()); + result->SetBoolean(keys::kHttpOnlyKey, cookie.IsHttpOnly()); + result->SetBoolean(keys::kSessionKey, !cookie.DoesExpire()); + if (cookie.DoesExpire()) + result->SetReal(keys::kExpirationDateKey, cookie.ExpiryDate().ToDoubleT()); + result->SetString(keys::kStoreIdKey, store_id); + + return result; +} + +DictionaryValue* CreateCookieStoreValue(Profile* profile, + ListValue* tab_ids) { + DCHECK(profile); + DCHECK(tab_ids); + DictionaryValue* result = new DictionaryValue(); + result->SetString(keys::kIdKey, GetStoreIdFromProfile(profile)); + result->Set(keys::kTabIdsKey, tab_ids); + return result; +} + +net::CookieMonster::CookieList GetCookieListFromStore( + net::CookieStore* cookie_store, const GURL& url) { + DCHECK(cookie_store); + net::CookieMonster* monster = cookie_store->GetCookieMonster(); + if (!url.is_empty()) { + DCHECK(url.is_valid()); + return monster->GetAllCookiesForURL(url); + } + return monster->GetAllCookies(); +} + +GURL GetURLFromCanonicalCookie( + const net::CookieMonster::CanonicalCookie& cookie) { + const std::string& domain_key = cookie.Domain(); + const std::string scheme = + cookie.IsSecure() ? chrome::kHttpsScheme : chrome::kHttpScheme; + const std::string host = + domain_key.find('.') != 0 ? domain_key : domain_key.substr(1); + return GURL(scheme + chrome::kStandardSchemeSeparator + host + "/"); +} + +void AppendMatchingCookiesToList( + const net::CookieMonster::CookieList& all_cookies, + const std::string& store_id, + const GURL& url, const DictionaryValue* details, + const Extension* extension, + ListValue* match_list) { + net::CookieMonster::CookieList::const_iterator it; + for (it = all_cookies.begin(); it != all_cookies.end(); ++it) { + // Ignore any cookie whose domain doesn't match the extension's + // host permissions. + GURL cookie_domain_url = GetURLFromCanonicalCookie(*it); + if (!extension->HasHostPermission(cookie_domain_url)) + continue; + // Filter the cookie using the match filter. + extension_cookies_helpers::MatchFilter filter(details); + if (filter.MatchesCookie(*it)) + match_list->Append(CreateCookieValue(*it, store_id)); + } +} + +void AppendToTabIdList(Browser* browser, ListValue* tab_ids) { + DCHECK(browser); + DCHECK(tab_ids); + TabStripModel* tab_strip = browser->tabstrip_model(); + for (int i = 0; i < tab_strip->count(); ++i) { + tab_ids->Append(Value::CreateIntegerValue( + ExtensionTabUtil::GetTabId(tab_strip->GetTabContentsAt(i)))); + } +} + +MatchFilter::MatchFilter(const DictionaryValue* details) + : details_(details) { + DCHECK(details_); +} + +bool MatchFilter::MatchesCookie( + const net::CookieMonster::CanonicalCookie& cookie) { + return + MatchesString(keys::kNameKey, cookie.Name()) && + MatchesDomain(cookie.Domain()) && + MatchesString(keys::kPathKey, cookie.Path()) && + MatchesBoolean(keys::kSecureKey, cookie.IsSecure()) && + MatchesBoolean(keys::kSessionKey, !cookie.DoesExpire()); +} + +bool MatchFilter::MatchesString(const wchar_t* key, const std::string& value) { + if (!details_->HasKey(key)) + return true; + std::string filter_value; + return (details_->GetString(key, &filter_value) && + value == filter_value); +} + +bool MatchFilter::MatchesBoolean(const wchar_t* key, bool value) { + if (!details_->HasKey(key)) + return true; + bool filter_value = false; + return (details_->GetBoolean(key, &filter_value) && + value == filter_value); +} + +bool MatchFilter::MatchesDomain(const std::string& domain) { + if (!details_->HasKey(keys::kDomainKey)) + return true; + + std::string filter_value; + if (!details_->GetString(keys::kDomainKey, &filter_value)) + return false; + // Add a leading '.' character to the filter domain if it doesn't exist. + if (net::CookieMonster::DomainIsHostOnly(filter_value)) + filter_value.insert(0, "."); + + std::string sub_domain(domain); + // Strip any leading '.' character from the input cookie domain. + if (!net::CookieMonster::DomainIsHostOnly(sub_domain)) + sub_domain = sub_domain.substr(1); + + // Now check whether the domain argument is a subdomain of the filter domain. + for (sub_domain.insert(0, "."); + sub_domain.length() >= filter_value.length();) { + if (sub_domain == filter_value) + return true; + const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot. + sub_domain.erase(0, next_dot); + } + return false; +} + +} // namespace extension_cookies_helpers |