1// Copyright 2013 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 "base/bind.h" 6#include "base/command_line.h" 7#include "base/memory/ref_counted.h" 8#include "chrome/browser/browser_shutdown.h" 9#include "chrome/browser/prefs/session_startup_pref.h" 10#include "chrome/browser/profiles/profile_io_data.h" 11#include "chrome/browser/ui/startup/startup_browser_creator.h" 12#include "content/public/browser/browser_context.h" 13#include "content/public/browser/browser_thread.h" 14#include "content/public/browser/dom_storage_context.h" 15#include "content/public/browser/local_storage_usage_info.h" 16#include "content/public/browser/storage_partition.h" 17#include "net/cookies/cookie_monster.h" 18#include "net/cookies/cookie_store.h" 19#include "net/cookies/cookie_util.h" 20#include "net/url_request/url_request_context.h" 21#include "storage/browser/quota/special_storage_policy.h" 22 23namespace { 24 25void CookieDeleted(bool success) { 26 DCHECK(success); 27} 28 29class SessionDataDeleter 30 : public base::RefCountedThreadSafe<SessionDataDeleter> { 31 public: 32 SessionDataDeleter(storage::SpecialStoragePolicy* storage_policy, 33 bool delete_only_by_session_only_policy); 34 35 void Run(content::StoragePartition* storage_partition, 36 ProfileIOData* profile_io_data); 37 38 private: 39 friend class base::RefCountedThreadSafe<SessionDataDeleter>; 40 ~SessionDataDeleter(); 41 42 // Deletes the local storage described by |usages| for origins which are 43 // session-only. 44 void ClearSessionOnlyLocalStorage( 45 content::StoragePartition* storage_partition, 46 const std::vector<content::LocalStorageUsageInfo>& usages); 47 48 // Deletes all cookies that are session only if 49 // |delete_only_by_session_only_policy_| is false. Once completed or skipped, 50 // this arranges for DeleteSessionOnlyOriginCookies to be called with a list 51 // of all remaining cookies. 52 void DeleteSessionCookiesOnIOThread(ProfileIOData* profile_io_data); 53 54 // Called when all session-only cookies have been deleted. 55 void DeleteSessionCookiesDone(int num_deleted); 56 57 // Deletes the cookies in |cookies| that are for origins which are 58 // session-only. 59 void DeleteSessionOnlyOriginCookies(const net::CookieList& cookies); 60 61 scoped_refptr<net::CookieMonster> cookie_monster_; 62 scoped_refptr<storage::SpecialStoragePolicy> storage_policy_; 63 const bool delete_only_by_session_only_policy_; 64 65 DISALLOW_COPY_AND_ASSIGN(SessionDataDeleter); 66}; 67 68SessionDataDeleter::SessionDataDeleter( 69 storage::SpecialStoragePolicy* storage_policy, 70 bool delete_only_by_session_only_policy) 71 : storage_policy_(storage_policy), 72 delete_only_by_session_only_policy_(delete_only_by_session_only_policy) { 73} 74 75void SessionDataDeleter::Run(content::StoragePartition* storage_partition, 76 ProfileIOData* profile_io_data) { 77 if (storage_policy_.get() && storage_policy_->HasSessionOnlyOrigins()) { 78 storage_partition->GetDOMStorageContext()->GetLocalStorageUsage( 79 base::Bind(&SessionDataDeleter::ClearSessionOnlyLocalStorage, 80 this, 81 storage_partition)); 82 } 83 content::BrowserThread::PostTask( 84 content::BrowserThread::IO, 85 FROM_HERE, 86 base::Bind(&SessionDataDeleter::DeleteSessionCookiesOnIOThread, 87 this, 88 profile_io_data)); 89} 90 91SessionDataDeleter::~SessionDataDeleter() {} 92 93void SessionDataDeleter::ClearSessionOnlyLocalStorage( 94 content::StoragePartition* storage_partition, 95 const std::vector<content::LocalStorageUsageInfo>& usages) { 96 DCHECK(storage_policy_.get()); 97 DCHECK(storage_policy_->HasSessionOnlyOrigins()); 98 for (size_t i = 0; i < usages.size(); ++i) { 99 const content::LocalStorageUsageInfo& usage = usages[i]; 100 if (!storage_policy_->IsStorageSessionOnly(usage.origin)) 101 continue; 102 storage_partition->GetDOMStorageContext()->DeleteLocalStorage(usage.origin); 103 } 104} 105 106void SessionDataDeleter::DeleteSessionCookiesOnIOThread( 107 ProfileIOData* profile_io_data) { 108 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 109 net::URLRequestContext* request_context = 110 profile_io_data->GetMainRequestContext(); 111 cookie_monster_ = request_context->cookie_store()->GetCookieMonster(); 112 if (delete_only_by_session_only_policy_) { 113 cookie_monster_->GetAllCookiesAsync( 114 base::Bind(&SessionDataDeleter::DeleteSessionOnlyOriginCookies, this)); 115 } else { 116 cookie_monster_->DeleteSessionCookiesAsync( 117 base::Bind(&SessionDataDeleter::DeleteSessionCookiesDone, this)); 118 } 119} 120 121void SessionDataDeleter::DeleteSessionCookiesDone(int num_deleted) { 122 cookie_monster_->GetAllCookiesAsync( 123 base::Bind(&SessionDataDeleter::DeleteSessionOnlyOriginCookies, this)); 124} 125 126void SessionDataDeleter::DeleteSessionOnlyOriginCookies( 127 const net::CookieList& cookies) { 128 if (!storage_policy_.get() || !storage_policy_->HasSessionOnlyOrigins()) 129 return; 130 131 for (net::CookieList::const_iterator it = cookies.begin(); 132 it != cookies.end(); 133 ++it) { 134 GURL url = 135 net::cookie_util::CookieOriginToURL(it->Domain(), it->IsSecure()); 136 if (!storage_policy_->IsStorageSessionOnly(url)) 137 continue; 138 cookie_monster_->DeleteCanonicalCookieAsync(*it, base::Bind(CookieDeleted)); 139 } 140} 141 142} // namespace 143 144void DeleteSessionOnlyData(Profile* profile) { 145 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 146 if (browser_shutdown::IsTryingToQuit()) 147 return; 148 149#if defined(OS_ANDROID) 150 SessionStartupPref::Type startup_pref_type = 151 SessionStartupPref::GetDefaultStartupType(); 152#else 153 SessionStartupPref::Type startup_pref_type = 154 StartupBrowserCreator::GetSessionStartupPref( 155 *CommandLine::ForCurrentProcess(), profile).type; 156#endif 157 158 scoped_refptr<SessionDataDeleter> deleter( 159 new SessionDataDeleter(profile->GetSpecialStoragePolicy(), 160 startup_pref_type == SessionStartupPref::LAST)); 161 deleter->Run( 162 Profile::GetDefaultStoragePartition(profile), 163 ProfileIOData::FromResourceContext(profile->GetResourceContext())); 164} 165