15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/net/cookie_store_util.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/callback.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/command_line.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/lazy_instance.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/browser_process.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chrome_notification_types.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/net/chrome_cookie_notification_details.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/net/evicted_domain_cookie_counter.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/prerender/prerender_manager.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/prerender/prerender_manager_factory.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_constants.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/os_crypt/os_crypt.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/cookie_crypto_delegate.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/cookie_store_factory.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/notification_service.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/common/content_constants.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/constants.h"
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::BrowserThread;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ChromeCookieMonsterDelegate : public net::CookieMonsterDelegate {
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit ChromeCookieMonsterDelegate(Profile* profile)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : profile_getter_(
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::Bind(&GetProfileOnUI, g_browser_process->profile_manager(),
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     profile)) {
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(profile);
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // net::CookieMonster::Delegate implementation.
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnCookieChanged(
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const net::CanonicalCookie& cookie,
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool removed,
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      net::CookieMonster::Delegate::ChangeCause cause) OVERRIDE {
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserThread::PostTask(
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BrowserThread::UI, FROM_HERE,
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&ChromeCookieMonsterDelegate::OnCookieChangedAsyncHelper,
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   this, cookie, removed, cause));
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnLoaded() OVERRIDE {
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    BrowserThread::PostTask(
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        BrowserThread::UI, FROM_HERE,
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&ChromeCookieMonsterDelegate::OnLoadedAsyncHelper,
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   this));
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~ChromeCookieMonsterDelegate() {}
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static Profile* GetProfileOnUI(ProfileManager* profile_manager,
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 Profile* profile) {
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (profile_manager->IsValidProfile(profile))
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return profile;
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnCookieChangedAsyncHelper(
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const net::CanonicalCookie& cookie,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool removed,
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      net::CookieMonster::Delegate::ChangeCause cause) {
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Profile* profile = profile_getter_.Run();
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (profile) {
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ChromeCookieDetails cookie_details(&cookie, removed, cause);
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content::NotificationService::current()->Notify(
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          chrome::NOTIFICATION_COOKIE_CHANGED,
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          content::Source<Profile>(profile),
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          content::Details<ChromeCookieDetails>(&cookie_details));
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void OnLoadedAsyncHelper() {
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Profile* profile = profile_getter_.Run();
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (profile) {
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      prerender::PrerenderManager* prerender_manager =
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          prerender::PrerenderManagerFactory::GetForProfile(profile);
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (prerender_manager)
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        prerender_manager->OnCookieStoreLoaded();
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Callback<Profile*(void)> profile_getter_;
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace chrome_browser_net {
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool IsCookieRecordMode() {
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Only allow Record Mode if we are in a Debug build or where we are running
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // a cycle, and the user has limited control.
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return command_line.HasSwitch(switches::kRecordMode) &&
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      chrome::kRecordModeEnabled;
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ShouldUseInMemoryCookiesAndCache() {
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return IsCookieRecordMode() ||
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      command_line.HasSwitch(switches::kPlaybackMode);
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)net::CookieMonsterDelegate* CreateCookieDelegate(Profile* profile) {
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new EvictedDomainCookieCounter(
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new ChromeCookieMonsterDelegate(profile));
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use the operating system's mechanisms to encrypt cookies before writing
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// them to persistent store.  Currently this only is done with desktop OS's
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// because ChromeOS and Android already protect the entire profile contents.
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(bcwhite): Enable on MACOSX -- requires all Cookie tests to call
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// OSCrypt::UseMockKeychain or will hang waiting for user input.
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class CookieOSCryptoDelegate : public content::CookieCryptoDelegate {
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool EncryptString(const std::string& plaintext,
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             std::string* ciphertext) OVERRIDE;
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool DecryptString(const std::string& ciphertext,
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             std::string* plaintext) OVERRIDE;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CookieOSCryptoDelegate::EncryptString(const std::string& plaintext,
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           std::string* ciphertext) {
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return OSCrypt::EncryptString(plaintext, ciphertext);
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CookieOSCryptoDelegate::DecryptString(const std::string& ciphertext,
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           std::string* plaintext) {
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return OSCrypt::DecryptString(ciphertext, plaintext);
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Using a LazyInstance is safe here because this class is stateless and
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// requires 0 initialization.
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::LazyInstance<CookieOSCryptoDelegate> g_cookie_crypto_delegate =
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)content::CookieCryptoDelegate* GetCookieCryptoDelegate() {
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return g_cookie_crypto_delegate.Pointer();
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)content::CookieCryptoDelegate* GetCookieCryptoDelegate() {
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NULL;
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace chrome_browser_net
165