1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/net/cookie_store_util.h" 6 7 #include "base/bind.h" 8 #include "base/callback.h" 9 #include "base/command_line.h" 10 #include "base/lazy_instance.h" 11 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/chrome_notification_types.h" 13 #include "chrome/browser/net/chrome_cookie_notification_details.h" 14 #include "chrome/browser/net/evicted_domain_cookie_counter.h" 15 #include "chrome/browser/prerender/prerender_manager.h" 16 #include "chrome/browser/prerender/prerender_manager_factory.h" 17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile_manager.h" 19 #include "chrome/common/chrome_constants.h" 20 #include "chrome/common/chrome_switches.h" 21 #include "components/os_crypt/os_crypt.h" 22 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/cookie_crypto_delegate.h" 24 #include "content/public/browser/cookie_store_factory.h" 25 #include "content/public/browser/notification_service.h" 26 #include "content/public/common/content_constants.h" 27 #include "extensions/common/constants.h" 28 29 using content::BrowserThread; 30 31 namespace { 32 33 class ChromeCookieMonsterDelegate : public net::CookieMonsterDelegate { 34 public: 35 explicit ChromeCookieMonsterDelegate(Profile* profile) 36 : profile_getter_( 37 base::Bind(&GetProfileOnUI, g_browser_process->profile_manager(), 38 profile)) { 39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 40 DCHECK(profile); 41 } 42 43 // net::CookieMonster::Delegate implementation. 44 virtual void OnCookieChanged( 45 const net::CanonicalCookie& cookie, 46 bool removed, 47 net::CookieMonster::Delegate::ChangeCause cause) OVERRIDE { 48 BrowserThread::PostTask( 49 BrowserThread::UI, FROM_HERE, 50 base::Bind(&ChromeCookieMonsterDelegate::OnCookieChangedAsyncHelper, 51 this, cookie, removed, cause)); 52 } 53 54 virtual void OnLoaded() OVERRIDE { 55 BrowserThread::PostTask( 56 BrowserThread::UI, FROM_HERE, 57 base::Bind(&ChromeCookieMonsterDelegate::OnLoadedAsyncHelper, 58 this)); 59 } 60 61 private: 62 virtual ~ChromeCookieMonsterDelegate() {} 63 64 static Profile* GetProfileOnUI(ProfileManager* profile_manager, 65 Profile* profile) { 66 if (profile_manager->IsValidProfile(profile)) 67 return profile; 68 return NULL; 69 } 70 71 void OnCookieChangedAsyncHelper( 72 const net::CanonicalCookie& cookie, 73 bool removed, 74 net::CookieMonster::Delegate::ChangeCause cause) { 75 Profile* profile = profile_getter_.Run(); 76 if (profile) { 77 ChromeCookieDetails cookie_details(&cookie, removed, cause); 78 content::NotificationService::current()->Notify( 79 chrome::NOTIFICATION_COOKIE_CHANGED, 80 content::Source<Profile>(profile), 81 content::Details<ChromeCookieDetails>(&cookie_details)); 82 } 83 } 84 85 void OnLoadedAsyncHelper() { 86 Profile* profile = profile_getter_.Run(); 87 if (profile) { 88 prerender::PrerenderManager* prerender_manager = 89 prerender::PrerenderManagerFactory::GetForProfile(profile); 90 if (prerender_manager) 91 prerender_manager->OnCookieStoreLoaded(); 92 } 93 } 94 95 const base::Callback<Profile*(void)> profile_getter_; 96 }; 97 98 } // namespace 99 100 namespace chrome_browser_net { 101 102 bool IsCookieRecordMode() { 103 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 104 // Only allow Record Mode if we are in a Debug build or where we are running 105 // a cycle, and the user has limited control. 106 return command_line.HasSwitch(switches::kRecordMode) && 107 chrome::kRecordModeEnabled; 108 } 109 110 bool ShouldUseInMemoryCookiesAndCache() { 111 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 112 return IsCookieRecordMode() || 113 command_line.HasSwitch(switches::kPlaybackMode); 114 } 115 116 net::CookieMonsterDelegate* CreateCookieDelegate(Profile* profile) { 117 return new EvictedDomainCookieCounter( 118 new ChromeCookieMonsterDelegate(profile)); 119 } 120 121 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 122 namespace { 123 124 // Use the operating system's mechanisms to encrypt cookies before writing 125 // them to persistent store. Currently this only is done with desktop OS's 126 // because ChromeOS and Android already protect the entire profile contents. 127 // 128 // TODO(bcwhite): Enable on MACOSX -- requires all Cookie tests to call 129 // OSCrypt::UseMockKeychain or will hang waiting for user input. 130 class CookieOSCryptoDelegate : public content::CookieCryptoDelegate { 131 public: 132 virtual bool EncryptString(const std::string& plaintext, 133 std::string* ciphertext) OVERRIDE; 134 virtual bool DecryptString(const std::string& ciphertext, 135 std::string* plaintext) OVERRIDE; 136 }; 137 138 bool CookieOSCryptoDelegate::EncryptString(const std::string& plaintext, 139 std::string* ciphertext) { 140 return OSCrypt::EncryptString(plaintext, ciphertext); 141 } 142 143 bool CookieOSCryptoDelegate::DecryptString(const std::string& ciphertext, 144 std::string* plaintext) { 145 return OSCrypt::DecryptString(ciphertext, plaintext); 146 } 147 148 // Using a LazyInstance is safe here because this class is stateless and 149 // requires 0 initialization. 150 base::LazyInstance<CookieOSCryptoDelegate> g_cookie_crypto_delegate = 151 LAZY_INSTANCE_INITIALIZER; 152 153 } // namespace 154 155 content::CookieCryptoDelegate* GetCookieCryptoDelegate() { 156 return g_cookie_crypto_delegate.Pointer(); 157 } 158 #else // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 159 content::CookieCryptoDelegate* GetCookieCryptoDelegate() { 160 return NULL; 161 } 162 #endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 163 164 } // namespace chrome_browser_net 165